Material, Compose UI, Foundation API는 기본적으로 접근 가능한 여러 권장사항을 구현하고 제공합니다. 특정 역할과 기능을 따르는 내장 시맨틱을 포함하므로 대부분의 접근성 지원은 추가 작업 없이 제공됩니다.
적절한 목적으로 적절한 API를 사용한다는 것은 일반적으로 구성요소에 표준 사용 사례를 다루는 사전 정의된 접근성 동작이 포함되어 있다는 것을 의미하지만 이러한 기본값이 접근성 요구사항에 적합한지 다시 한번 확인하세요. 그렇지 않은 경우 Compose는 더 구체적인 요구사항을 충족하는 방법도 제공합니다.
Compose API의 기본 접근성 시맨틱 및 패턴을 알면 접근성을 염두에 두고 이를 사용하는 방법을 이해하고 더 많은 맞춤 구성요소에서 접근성을 지원하는 데 도움이 됩니다.
터치 영역 최소 크기
사용자가 클릭, 터치 등의 방법으로 상호작용할 수 있는 화면상의 요소는 안정적으로 상호작용할 수 있도록 충분히 커야 합니다. 이러한 요소의 크기를 조절할 때 Material Design 접근성 가이드라인을 정확히 준수하도록 최소 크기를 48dp로 설정해야 합니다.
Checkbox
, RadioButton
, Switch
,
Slider
, Surface
와 같은 Material 구성요소는 이 최소 크기를 내부적으로 설정합니다. 단, 구성요소가 사용자 작업을 수신할 수 있는 경우에 한합니다. 예를 들어 Checkbox
의 onCheckedChange
매개변수가 null이 아닌 값으로 설정된 경우 체크박스에는 너비와 높이가 최소 48dp인 패딩이 포함됩니다.
@Composable private fun CheckableCheckbox() { Checkbox(checked = true, onCheckedChange = {}) }

onCheckedChange
매개변수가 null로 설정된 경우 구성요소와 직접 상호작용할 수 없으므로 패딩이 포함되지 않습니다.
@Composable private fun NonClickableCheckbox() { Checkbox(checked = true, onCheckedChange = null) }

Switch
, RadioButton
, Checkbox
와 같은 선택 설정을 구현할 경우 일반적으로 클릭 가능한 동작을 상위 컨테이너로 올리고, 컴포저블에 관한 클릭 콜백을 null
로 설정하고, toggleable
또는 selectable
수정자를 상위 컴포저블에 추가합니다.
@Composable private fun CheckableRow() { MaterialTheme { var checked by remember { mutableStateOf(false) } Row( Modifier .toggleable( value = checked, role = Role.Checkbox, onValueChange = { checked = !checked } ) .padding(16.dp) .fillMaxWidth() ) { Text("Option", Modifier.weight(1f)) Checkbox(checked = checked, onCheckedChange = null) } } }

클릭 가능한 컴포저블의 크기가 터치 영역 최소 크기보다 작은 경우 Compose는 여전히 터치 영역 크기를 늘립니다. 이 작업은 컴포저블의 경계 밖으로 터치 영역 크기를 확장하여 이뤄집니다.
다음 예에는 클릭 가능한 아주 작은 Box
가 포함되어 있습니다. 터치 영역 부분은 Box
의 경계 밖으로 자동으로 확장되므로 Box
옆을 탭하면 여전히 클릭 이벤트가 트리거됩니다.
@Composable private fun SmallBox() { var clicked by remember { mutableStateOf(false) } Box( Modifier .size(100.dp) .background(if (clicked) Color.DarkGray else Color.LightGray) ) { Box( Modifier .align(Alignment.Center) .clickable { clicked = !clicked } .background(Color.Black) .size(1.dp) ) } }

서로 다른 컴포저블의 터치 영역이 서로 겹치지 않도록 항상 컴포저블에 충분히 큰 최소 크기를 사용합니다. 이 예에서는 sizeIn
수정자를 사용하여 내부 상자의 최소 크기를 설정하는 것을 의미합니다.
@Composable private fun LargeBox() { var clicked by remember { mutableStateOf(false) } Box( Modifier .size(100.dp) .background(if (clicked) Color.DarkGray else Color.LightGray) ) { Box( Modifier .align(Alignment.Center) .clickable { clicked = !clicked } .background(Color.Black) .sizeIn(minWidth = 48.dp, minHeight = 48.dp) ) } }

그래픽 요소
Image
또는 Icon
컴포저블을 정의하는 경우 Android 프레임워크에서 앱이 표시하는 내용을 자동으로 파악할 수 없습니다. 그래픽 요소의 텍스트 설명을 전달해야 합니다.
사용자가 현재 페이지를 친구와 공유할 수 있는 화면이 있다고 가정해 보겠습니다. 이 화면에는 클릭 가능한 공유 아이콘이 포함되어 있습니다.

Android 프레임워크는 아이콘만 가지고는 시각 장애를 가진 사용자에게 아이콘에 대해 설명할 수 없습니다. Android 프레임워크에는 아이콘의 추가 텍스트 설명이 필요합니다.
contentDescription
매개변수는 그래픽 요소를 설명합니다. 사용자에게 표시되므로 현지화된 문자열을 사용합니다.
@Composable private fun ShareButton(onClick: () -> Unit) { IconButton(onClick = onClick) { Icon( imageVector = Icons.Filled.Share, contentDescription = stringResource(R.string.label_share) ) } }
일부 그래픽 요소는 완전히 장식용이므로 사용자에게 전달하지 않아도 됩니다. contentDescription
매개변수를 null
로 설정하면 Android 프레임워크에 이 요소에 연결된 작업 또는 상태가 없음을 나타냅니다.
@Composable private fun PostImage(post: Post, modifier: Modifier = Modifier) { val image = post.imageThumb ?: painterResource(R.drawable.placeholder_1_1) Image( painter = image, // Specify that this image has no semantic meaning contentDescription = null, modifier = modifier .size(40.dp, 40.dp) .clip(MaterialTheme.shapes.small) ) }
contentDescription
는 주로 이미지와 같은 그래픽 요소에 사용하기 위한 것입니다. Button
또는 Text
와 같은 Material 구성요소와 clickable
또는 toggleable
와 같은 실행 가능한 동작은 내재적 동작을 설명하는 다른 사전 정의된 시맨틱과 함께 제공되며 다른 Compose API를 통해 변경할 수 있습니다.
상호작용 요소
Material 및 Foundation Compose API는 사용자가 clickable
및 toggleable
수정자 API를 통해 상호작용할 수 있는 UI 요소를 만듭니다. 상호작용이 가능한 구성요소는 여러 요소로 구성될 수 있으므로 clickable
및 toggleable
는 기본적으로 하위 요소의 시맨틱을 병합하여 구성요소가 하나의 논리적 항목으로 취급되도록 합니다.
예를 들어 Material Button
는 하위 아이콘과 텍스트로 구성될 수 있습니다.
Material Button은 하위 요소를 개별적으로 취급하는 대신 접근성 서비스가 적절하게 그룹화할 수 있도록 기본적으로 하위 요소 시맨틱스를 병합합니다.

마찬가지로 clickable
수정자를 사용하면 컴포저블이 하위 요소의 시맨틱을 단일 항목으로 병합하여 해당 작업 표현과 함께 접근성 서비스로 전송합니다.
Row( // Uses `mergeDescendants = true` under the hood modifier = Modifier.clickable { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open", ) Text("Accessibility in Compose") }
클릭 가능한 상위 요소에 특정 onClickLabel
를 설정하여 접근성 서비스에 추가 정보를 제공하고 작업을 더 세련되게 표현할 수도 있습니다.
Row( modifier = Modifier .clickable(onClickLabel = "Open this article") { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open" ) Text("Accessibility in Compose") }
TalkBack을 예로 들면 이 clickable
수정자와 클릭 라벨을 사용하면 TalkBack에서 '두 번 탭하여 이 도움말 열기'와 같은 작업 힌트를 제공할 수 있습니다. 이는 더 일반적인 기본 피드백인 '두 번 탭하여 활성화'보다 유용합니다.
이 의견은 작업 유형에 따라 달라집니다. 길게 클릭하면 '길게 두 번 탭하여'라는 TalkBack 힌트와 라벨이 표시됩니다.
Row( modifier = Modifier .combinedClickable( onLongClickLabel = "Bookmark this article", onLongClick = { addToBookmarks() }, onClickLabel = "Open this article", onClick = { openArticle() }, ) ) {}
경우에 따라 clickable
수정자에 직접 액세스할 수 없지만 (예: 하위 중첩 레이어의 어딘가에 설정된 경우) 공지사항 라벨을 기본값에서 변경하려고 할 수 있습니다. 이렇게 하려면 semantics
수정자를 사용하여 clickable
설정을 공지사항 수정과 분리하고 클릭 라벨을 설정하여 작업 표현을 수정합니다.
@Composable private fun ArticleList(openArticle: () -> Unit) { NestedArticleListItem( // Clickable is set separately, in a nested layer: onClickAction = openArticle, // Semantics are set here: modifier = Modifier.semantics { onClick( label = "Open this article", action = { // Not needed here: openArticle() true } ) } ) }
이 경우 clickable
또는 Button
와 같은 기존 Compose API가 이를 대신 처리하므로 클릭 작업을 두 번 전달할 필요가 없습니다. 이는 병합 로직이 존재하는 정보에 대해 가장 바깥쪽 수정자 라벨과 작업이 실행되도록 하기 때문입니다.
이전 예에서 openArticle()
클릭 작업은 NestedArticleListItem
에 의해 자동으로 clickable
시맨틱 아래로 전달되며 두 번째 시맨틱 수정자 작업에서 null로 둘 수 있습니다. 그러나 클릭 라벨은 첫 번째에 없으므로 두 번째 시맨틱 수정자 onClick(label = "Open this article")
에서 가져옵니다.
하위 시맨틱이 상위 시맨틱으로 병합될 것으로 예상되지만 실제로는 그렇지 않은 시나리오가 발생할 수 있습니다. 자세한 내용은 병합 및 삭제를 참고하세요.
맞춤 구성요소
맞춤 구성요소의 경우 일반적으로 Material 라이브러리 또는 다른 Compose 라이브러리에서 유사한 구성요소의 구현을 살펴보고, 적절한 경우 접근성 동작을 모방하거나 수정합니다.
예를 들어 Material Checkbox
를 자체 구현으로 대체하는 경우 기존 체크박스 구현을 살펴보면 이 구성요소의 접근성 속성을 처리하는 triStateToggleable
수정자를 추가해야 한다는 것을 알 수 있습니다.
또한 Foundation 수정자를 많이 활용하세요. Foundation 수정자에는 접근성 고려 사항이 기본적으로 포함되어 있으며 이 섹션에서 다루는 기존 Compose 관행도 포함되어 있습니다.
세맨틱 지우기 및 설정 섹션에서 맞춤 전환 버튼 구성요소의 예를 확인할 수 있으며 API 가이드라인에서 맞춤 구성요소의 접근성을 지원하는 방법에 관한 자세한 내용을 확인할 수 있습니다.
추천 서비스
- 참고: JavaScript가 사용 중지되어 있으면 링크 텍스트가 표시됩니다.
- Compose의 접근성
- [Compose의 Material Design 2][19]
- Compose 레이아웃 테스트