組合可用來描述應用程式的 UI,可透過執行可組合項產生。組合是一種樹狀結構,由描述您的 UI 的可組合函式組成。
Composition 旁邊有一個平行樹狀結構,稱為「語意樹狀圖」。這個樹狀結構會以無障礙服務和測試架構能夠理解的替代方式描述 UI。無障礙服務會使用樹狀圖,向有特定需求的使用者描述應用程式。測試架構會使用這個樹狀結構與應用程式互動,並做出斷言。語意樹狀圖不含如何「繪製」可組合元件的資訊,但包含可組合元件語意意義的相關資訊。
如果您的應用程式是由 Compose 基礎和材質庫的可組合元件和修飾元組成,系統會自動為您產生並填入語義樹狀圖。不過,在新增自訂的低層級可組合項時,必須手動提供語意。在某些情況下,您的樹狀結構可能無法正確或完整反映螢幕上的元素含義,這時您只要調整樹狀結構即可。
以這個自訂日曆可組合元件為例:
在這個例子中,系統會使用Layout
可組合元件且直接繪製入Canvas
,從而將整個日曆作為單一低層級元件納入其中。如果您不採取任何其他行動,無障礙服務將無法收到有關可組合元件內容的資訊,也無法收到使用者在日曆中的選取資訊。舉例來說,如果使用者點擊包含 17 的日期,無障礙架構只會接收整個日曆控制項的說明資訊。在這種情況下,TalkBack 無障礙服務會說出「日曆」音訊,較好的情況下會說出「四月份日曆」,而使用者無法知道到底選取了哪一天。如要讓這個可組合項更容易存取,您必須手動新增語意資訊。
語義屬性
UI 樹狀圖中的所有節點都具有語義含義,這些節點在語義樹狀圖中具有平行節點。語義樹狀圖中的節點所包含的屬性能夠傳達對應可組合元件的意義。舉例來說,Text
可組合項包含語意屬性 text
,因為這是該可組合項的「含義」。Icon
包含 contentDescription
屬性 (若由開發人員設定),該屬性透過文字形式提供 Icon
的含義。建立在 Compose 基礎程式庫之上的可組合元件和修飾詞已經為您設定了相關屬性。視需要使用 semantics
和 clearAndSetSemantics
修飾符自行設定或覆寫屬性。舉例來說,您可以在節點中新增自訂無障礙動作、為可切換元素提供替代的狀態說明,或是指出特定文字可組合項應視為標題。
如要以視覺化方式呈現語意樹狀結構,請使用版面配置檢查器工具,或在測試中使用 printToLog()
方法。這會在 Logcat 中顯示目前的語意樹狀圖。
class MyComposeTest { @get:Rule val composeTestRule = createComposeRule() @Test fun MyTest() { // Start the app composeTestRule.setContent { MyTheme { Text("Hello world!") } } // Log the full semantics tree composeTestRule.onRoot().printToLog("MY TAG") } }
這項測試的輸出內容如下:
Printing with useUnmergedTree = 'false'
Node #1 at (l=0.0, t=63.0, r=221.0, b=120.0)px
|-Node #2 at (l=0.0, t=63.0, r=221.0, b=120.0)px
Text = '[Hello world!]'
Actions = [GetTextLayoutResult]
思考語意屬性如何傳達可組合元件的含義。以 Switch
為例。使用者所看到的畫面如下:
如要描述這個元素的含義,您可以說:"這是一個開關,這是處於「On」狀態的可切換元素。只要按一下即可與其互動。」
這就是語義屬性的用途。這個 Switch 元素的語意節點包含下列屬性,如版面配置檢查器所示:
Role
代表元素類型。StateDescription
說明瞭應如何參照「開啟」狀態。根據預設,這是「開啟」一詞的本地化版本,但您可以根據背景資訊更明確 (例如「已啟用」)。ToggleableState
是切換按鈕的目前狀態。OnClick
屬性會參照與此元素互動的方法。如需語意屬性的完整清單,請參閱 SemanticsProperties
物件。如需完整的無障礙操作清單,請參閱 SemanticsActions
物件。
追蹤應用程式中不同元件的語義屬性,藉此發掘許多強大的功能。以下列舉部分範例:
- Talkback 使用屬性朗讀螢幕上顯示的內容,讓使用者順暢與這些內容互動。在 Switch 可組合項中,TalkBack 可能會顯示:「On; Switch;輕觸兩下即可切換」。使用者只要輕觸兩下螢幕,即可將切換按鈕設為關閉。
-
測試架構會使用屬性尋找節點、與節點互動以及進行宣告。以下是切換開關的測試範例:
val mySwitch = SemanticsMatcher.expectValue( SemanticsProperties.Role, Role.Switch ) composeTestRule.onNode(mySwitch) .performClick() .assertIsOff()
合併及未合併的語義樹狀圖
如前文所述,UI 樹狀圖中每個可組合元件可能沒有或是有多個語義屬性設定。如果可組合元件沒有語意屬性設定,系統無法將其列入語意樹狀結構。那樣的話,語義樹狀圖僅包含真正含有語義含義的節點。但是,有時為了正確傳遞熒幕上呈現的含義,合併某些節點的子樹系並將其視為一體還是很有幫助的。如此一來,您就能將一組節點當做一個整體進行推理,而非單獨處理每個子節點。根據經驗,在使用無障礙服務時,這個樹狀圖中的每個節點都代表了一個可聚焦元素。
這類可組合項的範例便是 Button
。一個按鈕可以視為單一元素,即使它可能包含多個子節點:
Button(onClick = { /*TODO*/ }) { Icon( imageVector = Icons.Filled.Favorite, contentDescription = null ) Spacer(Modifier.size(ButtonDefaults.IconSpacing)) Text("Like") }
在 Semantics 樹狀圖中,該按鈕的子系屬性會合併,且按鈕在樹狀結構中會顯示為單一分葉節點:
可組合元件和修飾元可透過呼叫 Modifier.semantics
(mergeDescendants = true) {}
來合併其子系的語義屬性。如果將這個屬性設定為 true
,則表示應該合併語義屬性。在 Button
範例中,Button
可組合項在內部使用包含此 semantics
修飾符的 clickable
修飾符。因此,系統會合併該按鈕的子系節點。請參閱無障礙說明文件,進一步瞭解何時應在可組合元件中變更合併行為。
基礎與資料 Compose 程式庫中的數個修飾元和可組合元件具有該屬性設定。例如,clickable
和 toggleable
修飾元會自動合併它們的子系。此外,ListItem
可組合元件也會合併其子系。
檢查樹狀圖
語意樹狀圖實際上有兩個不同的樹狀結構。其中一個是「已合併」的語意樹狀結構,後者會在 mergeDescendants
設為 true
時合併子系節點。此外,還有一個「未合併」的語意樹狀圖,該樹狀圖不會套用合併規則,但會保留所有節點。無障礙服務會使用未合併的樹狀結構,並套用自己的合併演算法,並將 mergeDescendants
屬性納入考量。根據預設,測試架構會使用合併的樹狀結構。
您可以使用 printToLog()
方法檢查這兩種樹狀圖。根據預設,與先前的範例一樣,系統會記錄合併的樹狀結構。如要改為列印未合併的樹狀結構,請將 onRoot()
比對器的 useUnmergedTree
參數設為 true
:
composeTestRule.onRoot(useUnmergedTree = true).printToLog("MY TAG")
版面配置檢查器可讓您在檢視畫面篩選器中選取偏好的樹狀圖,藉此顯示合併和未合併的 Semantics 樹狀圖:
針對樹狀圖中的每個節點,版面配置檢查器會顯示其合併語義和屬性面板中該節點的語義設定:
根據預設,測試架構中的比對器會使用已合併的語義樹狀圖。因此,您可以透過比對 Button
內顯示的文字來與之互動:
composeTestRule.onNodeWithText("Like").performClick()
如要覆寫這個行為,請將比對器的 useUnmergedTree
參數設為 true
,做法與 onRoot
比對器相同。
合併行為
當一個可組合元件表示應該合併其子系,那麼這種合併到底是如何進行的?
每個語義屬性都有已定義的合併策略。舉例來說,ContentDescription
屬性會將所有子系 ContentDescription 值新增至清單。如要檢查語意屬性的合併策略,請前往 SemanticsProperties.kt
查看其 mergePolicy
實作項目。屬性可採用父項或子項值、將值合併至清單或字串、完全不允許合併並擲回例外狀況,或任何其他自訂合併策略。
重要的是,本身已設定 mergeDescendants
= true
的子係不會納入合併作業中。範例如下:
以下是可點擊的清單項目。使用者按一下該列時,應用程式會前往文章詳細資料頁面,使用者便可閱讀文章。清單項目內有一個按鈕,可將文章加入書籤,它形成一個巢狀可點擊元素,因此按鈕會分別顯示在合併的樹狀結構中。該列中其餘內容已被合併:
調整語意樹狀圖
如前所述,您可以覆寫或清除特定語意屬性,或是變更樹狀結構的合併行為。當您要建立自訂元件時,這一點尤其重要。如果沒有設定正確的屬性和合併行為,您的應用程式可能會無法存取,而且測試的行為可能會與您預期的不同。如果想進一步瞭解在哪些常見用途中應調整語意樹狀圖,請參閱無障礙功能說明文件。如要進一步瞭解測試,請參閱測試指南。
其他資源
- 無障礙設計:所有 Android 應用程式開發作業常見的基本概念和技巧
- 建構無障礙應用程式:您可以透過幾個重要步驟來打造無障礙應用程式
- 提升應用程式無障礙程度的基本原則:改善應用程式的無障礙設計時,請記住下列重要原則
- 無障礙設計測試:測試 Android 無障礙功能的原則和工具
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- Compose 中的無障礙功能
- Compose 中的質感設計 2
- 測試 Compose 版面配置