無障礙服務在瀏覽畫面上的元素時,請務必以適當的精細程度將這些元素分組、分隔或隱藏。如果畫面上的每個低階可組合項各自醒目顯示,使用者就必須互動許多次才能在畫面上移動。如果元素過度合併,問題就變成使用者可能不知道哪些元素屬於同一群組。如果畫面上有純裝飾性的元素,可以對無障礙服務隱藏。在這種情況下,您可以使用 Compose API 合併、清除及隱藏語意。
合併語意
將 clickable 修飾符套用至父項可組合項時,Compose 會自動合併其下的所有子項元素。如要瞭解互動式 Compose Material 和 Foundation 元件預設如何使用合併策略,請參閱「互動元素」一節。
元件通常由多個可組合項組成。這些可組合項可組成邏輯群組,且每個可組合項都可能包含重要資訊,但您仍希望無障礙服務將其視為單一元素。
舉例來說,假設可組合項會顯示使用者的顯示圖片、使用者名稱和一些額外資訊:

您可以在語意修飾符中使用 mergeDescendants 參數,讓 Compose 合併這些元素。這樣一來,無障礙服務會將元件視為單一實體,並合併子系的所有語意屬性:
@Composable private fun PostMetadata(metadata: Metadata) { // Merge elements below for accessibility purposes Row(modifier = Modifier.semantics(mergeDescendants = true) {}) { Image( imageVector = Icons.Filled.AccountCircle, contentDescription = null // decorative ) Column { Text(metadata.author.name) Text("${metadata.date} • ${metadata.readTimeMinutes} min read") } } }
無障礙服務現在一次聚焦於整個容器,並合併其內容:

每個語義屬性都有已定義的合併策略。舉例來說,ContentDescription 屬性會將所有子系 ContentDescription 值新增至清單。如要檢查語義屬性的合併策略,請前往 SemanticsProperties.kt 查看其 mergePolicy 實作項目。屬性可以採用父項或子項值、將值合併至清單或字串、完全不允許合併且擲回例外狀況,或任何其他自訂合併策略。
在其他情況下,您可能希望將子項語意合併至父項語意,但系統並未執行這項操作。在以下範例中,我們有一個 clickable 清單項目父項,其中包含子項元素,我們可能預期父項會合併所有元素:

@Composable private fun ArticleListItem( openArticle: () -> Unit, addToBookmarks: () -> Unit, ) { Row(modifier = Modifier.clickable { openArticle() }) { // Merges with parent clickable: Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Article thumbnail" ) ArticleDetails() // Defies the merge due to its own clickable: BookmarkButton(onClick = addToBookmarks) } }
使用者按下 clickable 項目 Row 時,系統會開啟文章。其中包含一個 BookmarkButton,可用來將文章加入書籤。這個巢狀按鈕會顯示為未合併,而資料列中的其餘子項內容則會合併:
Row 節點內的清單中包含多個文字。未合併的樹狀結構包含每個 Text 可組合項的獨立節點。根據設計,某些可組合項不會自動合併在父項下。如果子項也正在合併 (無論是透過明確設定 mergeDescendants = true,還是透過自行合併的元件,例如按鈕或可點擊項目),父項就無法合併子項。瞭解特定 API 的合併或不合併方式,有助於您對某些潛在的非預期行為進行偵錯。
當子項元素在父項下構成邏輯和合理的群組時,請使用合併。不過,如果巢狀子項需要手動調整或移除自己的語意,其他 API 可能更符合您的需求 (例如 clearAndSetSemantics)。
清除並設定語意
如需完全清除或覆寫語意資訊,可以使用強大的 API clearAndSetSemantics。
當元件需要清除本身和子系的語意時,請使用這個 API 搭配空白 lambda。如需覆寫語意,請在 lambda 中加入新內容。
請注意,使用空白 lambda 清除時,清除的語意不會傳送給任何使用這項資訊的消費者,例如無障礙功能、自動填入或測試。使用 clearAndSetSemantics{/*semantic information*/} 覆寫內容時,新語意會取代元素及其子系的所有先前語意。
以下是自訂切換鈕元件的範例,由可互動的資料列組成,內含圖示和文字:
// Developer might intend this to be a toggleable. // Using `clearAndSetSemantics`, on the Row, a clickable modifier is applied, // a custom description is set, and a Role is applied. @Composable fun FavoriteToggle() { val checked = remember { mutableStateOf(true) } Row( modifier = Modifier .toggleable( value = checked.value, onValueChange = { checked.value = it } ) .clearAndSetSemantics { stateDescription = if (checked.value) "Favorited" else "Not favorited" toggleableState = ToggleableState(checked.value) role = Role.Switch }, ) { Icon( imageVector = Icons.Default.Favorite, contentDescription = null // not needed here ) Text("Favorite?") } }
雖然圖示和文字含有一些語意資訊,但兩者結合後並未指出這個元件可切換。合併是不夠的,因為您必須提供元件的其他資訊。
由於上述程式碼片段會建立自訂切換鈕元件,因此您需要新增切換功能,以及 stateDescription、toggleableState 和 role 語意。這樣一來,系統就會提供元件狀態和相關聯的動作,例如 TalkBack 會朗讀「輕觸兩下即可切換」,而不是「輕觸兩下即可啟用」。
清除原始語意並設定更具描述性的新語意後,無障礙服務現在可以辨識出這是一個可切換狀態的元件。
使用 clearAndSetSemantics 時,請注意下列事項:
- 設定這個 API 後,服務就不會收到任何資訊,因此建議您謹慎使用。
- AI 代理和類似服務可能會使用語意資訊來瞭解畫面,因此只有在必要時才應清除。
- 您可以在 API lambda 中設定自訂語意。
- 修飾符的順序很重要,無論其他合併策略為何,這個 API 都會清除套用位置之後的所有語意。
隱藏語意
在某些情況下,元素不需要傳送至無障礙服務,例如額外資訊對無障礙功能而言是多餘的,或純粹是視覺裝飾且不具互動性。在這種情況下,您可以使用 hideFromAccessibility API 隱藏元素。
在以下範例中,可能需要隱藏的元件包括:橫跨元件的多餘浮水印,以及用於裝飾性分隔資訊的字元。
@Composable fun WatermarkExample( watermarkText: String, content: @Composable () -> Unit, ) { Box { WatermarkedContent() // Mark the watermark as hidden to accessibility services. WatermarkText( text = watermarkText, color = Color.Gray.copy(alpha = 0.5f), modifier = Modifier .align(Alignment.BottomEnd) .semantics { hideFromAccessibility() } ) } } @Composable fun DecorativeExample() { Text( modifier = Modifier.semantics { hideFromAccessibility() }, text = "A dot character that is used to decoratively separate information, like •" ) }
在這裡使用 hideFromAccessibility 可確保浮水印和裝飾不會向無障礙服務顯示,但仍會保留其他用途 (例如測試) 的語意。
用途細目
以下是用途摘要,可協助您瞭解如何清楚區分先前的 API:
- 如果內容不適合無障礙服務使用:
- 如果內容可能只是裝飾或多餘,但仍須測試,請使用
hideFromAccessibility。 - 如需清除所有服務的父項和子項語意,請使用
clearAndSetSemantics{}搭配空白 lambda。 - 當需要手動設定元件的語意時,請使用
clearAndSetSemantics{/*content*/},並在 lambda 中加入內容。
- 如果內容可能只是裝飾或多餘,但仍須測試,請使用
- 當內容應視為單一實體,且需要所有子項的資訊才能完整呈現時:
- 使用合併語意子系。
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- Compose 中的無障礙功能
- [Compose 中的 Material Design 2][19]
- 測試 Compose 版面配置