기본적으로 Compose 앱의 접근성 스크린 리더 동작이 구현됩니다.
읽을 수 있습니다. 일반적으로 왼쪽에서 오른쪽 순으로 읽은 후 위에서 아래로 읽히도록 하겠습니다.
그러나 알고리즘이 결정할 수 없는 앱 레이아웃 유형도 있습니다.
읽기 순서를 변경할 수 있습니다. 뷰 기반 앱에서는 다음 작업을 할 수 있습니다.
traversalBefore
및 traversalAfter
속성을 사용하여 이러한 문제를 해결하세요.
Compose 1.5부터 Compose는 똑같이 유연한 API를 제공하지만
새로운 개념 모델입니다.
isTraversalGroup
및 traversalIndex
는 시맨틱 속성입니다.
사용하면
기본 정렬 알고리즘이 적절하지 않습니다. isTraversalGroup
는
의미론적으로 중요한 그룹인 반면, traversalIndex
는
개별 요소를 구별할 수 있어야 합니다. isTraversalGroup
만 단독으로 사용할 수 있습니다.
또는 traversalIndex
를 사용하여 추가 맞춤설정을 수행합니다.
다음에서 isTraversalGroup
및 traversalIndex
사용:
앱을 사용하여 스크린 리더의 순회 순서를 제어할 수 있습니다.
isTraversalGroup
를 사용하여 요소 그룹화
isTraversalGroup
는 시맨틱
순회 그룹입니다. 이 유형의 노드는
노드의 하위 요소를 구성할 때 경계 또는 경계로 사용됩니다.
노드에서 isTraversalGroup = true
를 설정하면 해당 노드의 모든 하위 요소가
다른 요소로 이동하기 전에 사용자가 방문했는지 확인합니다. 다음에서 isTraversalGroup
설정 가능:
스크린 리더가 아닌 포커스 가능 노드(예: 열, 행, 상자)
다음 예에서는 isTraversalGroup
를 사용합니다. 4개의 텍스트 요소를 내보냅니다. 이
왼쪽 두 요소는 하나의 CardBox
요소에 속하고, 오른쪽 두 요소는
다른 CardBox
요소에 속할 수 있습니다.
// CardBox() function takes in top and bottom sample text. @Composable fun CardBox( topSampleText: String, bottomSampleText: String, modifier: Modifier = Modifier ) { Box(modifier) { Column { Text(topSampleText) Text(bottomSampleText) } } } @Composable fun TraversalGroupDemo() { val topSampleText1 = "This sentence is in " val bottomSampleText1 = "the left column." val topSampleText2 = "This sentence is " val bottomSampleText2 = "on the right." Row { CardBox( topSampleText1, bottomSampleText1 ) CardBox( topSampleText2, bottomSampleText2 ) } }
이 코드는 다음과 비슷한 출력을 생성합니다.
![텍스트 2열로 구성된 레이아웃과 왼쪽 열에 '이
문장이 왼쪽 열에 있는지 오른쪽 열에 'This sentence is on the right'이 표시됩니다](https://developer.android.google.cn/static/develop/ui/compose/images/a11y-istraversalgroup-example.png?authuser=2&hl=ko)
의미 체계가 설정되지 않았으므로 스크린 리더의 기본 동작은 다음과 같습니다. 왼쪽에서 오른쪽으로, 위에서 아래로 요소를 순회합니다. 그렇기 때문에 기본적으로 TalkBack은 문장 조각을 잘못된 순서로 읽습니다.
'This sentence is in' → 'This sentence is' → '왼쪽 열' → 되었습니다."라고 말합니다.
프래그먼트를 올바르게 정렬하려면 원래 스니펫을 수정하여
isTraversalGroup
에서 true
로:
@Composable fun TraversalGroupDemo2() { val topSampleText1 = "This sentence is in " val bottomSampleText1 = "the left column." val topSampleText2 = "This sentence is" val bottomSampleText2 = "on the right." Row { CardBox( // 1, topSampleText1, bottomSampleText1, Modifier.semantics { isTraversalGroup = true } ) CardBox( // 2, topSampleText2, bottomSampleText2, Modifier.semantics { isTraversalGroup = true } ) } }
isTraversalGroup
가 각 CardBox
에 구체적으로 설정되므로 CardBox
는
경계가 적용됩니다. 이 경우 왼쪽
CardBox
를 먼저 읽은 후 오른쪽 CardBox
를 읽습니다.
이제 TalkBack이 문장 조각을 올바른 순서로 읽습니다.
'This sentence is in' → '왼쪽 열' → 'This sentence is' → 되었습니다."라고 말합니다.
순회 순서 추가 맞춤설정
traversalIndex
는 TalkBack을 맞춤설정할 수 있는 부동 소수점 속성입니다.
있습니다. 요소를 그룹화하는 것만으로는 TalkBack이
traversalIndex
를 다음과 함께 사용하세요.
isTraversalGroup
: 스크린 리더 순서를 추가로 맞춤설정합니다.
traversalIndex
속성에는 다음과 같은 특성이 있습니다.
traversalIndex
값이 낮은 요소부터 우선순위가 부여됩니다.- 양수 또는 음수가 될 수 있습니다.
- 기본값은
0f
입니다. - 화면 내 요소와 같이 스크린 리더에 포커스를 맞출 수 있는 노드만
만들 수 있습니다. 예를 들어 열에
traversalIndex
만 설정하면 열에isTraversalGroup
가 설정되어 있지 않으면 아무 효과가 없습니다.
다음 예는 traversalIndex
및
isTraversalGroup
함께 사용할 수 있습니다.
예: 트래버스 시계 페이스
시계 페이스는 표준 순회 순서가 일치하지 않는 일반적인 시나리오입니다. 있습니다 이 섹션의 예는 사용자가 한 번에 이동할 수 있는 시간 선택 도구입니다. 시계 페이스의 숫자를 살펴보고 시간과 분을 나타내는 숫자를 선택하세요. 있습니다.
![위에 시간 선택기가 표시된 시계 페이스](https://developer.android.google.cn/static/develop/ui/compose/images/a11y-clock-face.png?authuser=2&hl=ko)
다음의 단순화된 스니펫에는 12의 값이 있는 CircularLayout
가 있습니다.
12부터 시작하여 원 주위를 시계 방향으로 이동하는 숫자가 그려집니다.
@Composable fun ClockFaceDemo() { CircularLayout { repeat(12) { hour -> ClockText(hour) } } } @Composable private fun ClockText(value: Int) { Box(modifier = Modifier) { Text((if (value == 0) 12 else value).toString()) } }
시계 페이스는 기본값인 왼쪽에서 오른쪽 방향으로 논리적으로 읽히지 않기 때문입니다. 위에서 아래로 정렬하면 TalkBack에서 숫자를 순서에 맞지 않게 읽습니다. 정정하다 다음 스니펫과 같이 증분 카운터 값을 사용합니다.
@Composable fun ClockFaceDemo() { CircularLayout(Modifier.semantics { isTraversalGroup = true }) { repeat(12) { hour -> ClockText(hour) } } } @Composable private fun ClockText(value: Int) { Box(modifier = Modifier.semantics { this.traversalIndex = value.toFloat() }) { Text((if (value == 0) 12 else value).toString()) } }
순회 순서를 올바르게 설정하려면 먼저 CircularLayout
를
순회 그룹을 사용하고 isTraversalGroup = true
를 설정합니다. 그런 다음 각 시계 텍스트가
레이아웃에 그려지고 상응하는 traversalIndex
를 카운터로 설정
값으로 사용됩니다.
카운터 값이 계속 증가하기 때문에 각 시계 값의
traversalIndex
은 화면에 숫자가 추가됨(시계 값 0)
traversalIndex
는 0이고 시계 값 1의 traversalIndex
는 1입니다.
이렇게 하면 TalkBack에서 읽는 순서가 설정됩니다. 이 수치는
CircularLayout
내부를 예상한 순서대로 읽음
설정된 traversalIndexes
는
색인을 생성할 때 화면 순서의 나머지 부분은
보존됩니다. 즉, 위 코드에 표시된 시맨틱 변경사항은
스니펫은
isTraversalGroup = true
설정됨.
CircularLayout's
시맨틱스를 isTraversalGroup =
true
로 설정하지 않아도 traversalIndex
변경사항이 계속 적용됩니다. 그러나
CircularLayout
를 사용하여 바인딩하면 시계 페이스의 12자리 숫자를 읽음
마지막으로, 화면의 다른 모든 요소를 방문한 후에 이는
다른 모든 요소의 기본 traversalIndex
가 0f
이고
시계 텍스트 요소는 다른 모든 0f
요소 이후에 읽습니다.
예: 플로팅 작업 버튼의 순회 순서 맞춤설정
이 예에서 traversalIndex
와 isTraversalGroup
는
머티리얼 디자인 플로팅 작업 버튼 (FAB)의 순회 순서 지정 기본
레이아웃은 다음과 같습니다.
![상단 앱 바, 샘플 텍스트, 플로팅 작업 버튼이 있는 레이아웃
표시됩니다.](https://developer.android.google.cn/static/develop/ui/compose/images/a11y-fab-example.png?authuser=2&hl=ko)
기본적으로 이 예의 레이아웃에는 다음과 같은 TalkBack 순서가 있습니다.
상단 앱 바 → 샘플 텍스트 0~6 → 플로팅 작업 버튼 (FAB) → 하단 앱 바
스크린 리더가 먼저 FAB에 포커스를 맞추는 것이 좋습니다. 설정
FAB와 같은 Material 요소에 traversalIndex
를 추가하려면 다음 단계를 따르세요.
@Composable fun FloatingBox() { Box(modifier = Modifier.semantics { isTraversalGroup = true; traversalIndex = -1f }) { FloatingActionButton(onClick = {}) { Icon(imageVector = Icons.Default.Add, contentDescription = "fab icon") } } }
이 스니펫에서는
isTraversalGroup
를 true
로 설정하고 같은 상자에 traversalIndex
를 설정합니다.
(-1f
이 기본값 0f
보다 작음) 플로팅 상자는
화면의 다른 모든 요소보다 앞에 옵니다.
다음으로 플로팅 상자와 기타 요소를 Scaffold에 넣을 수 있습니다. Material Design 레이아웃 구현:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun ColumnWithFABFirstDemo() { Scaffold( topBar = { TopAppBar(title = { Text("Top App Bar") }) }, floatingActionButtonPosition = FabPosition.End, floatingActionButton = { FloatingBox() }, content = { padding -> ContentColumn(padding = padding) }, bottomBar = { BottomAppBar { Text("Bottom App Bar") } } ) }
TalkBack은 다음 순서로 요소와 상호작용합니다.
FAB → 상단 앱 바 → 샘플 텍스트 0~6 → 하단 앱 바
추가 리소스
- 접근성: 필수 개념 및 모든 Android 앱 개발에 공통으로 적용되는 기법
- 액세스 가능한 앱 빌드: 주요 단계 앱의 접근성을 높이기 위해
- 앱 개선 원칙 접근성: 앱의 접근성을 높이기 위해 작업할 때 명심하세요
- 접근성 테스트: Android 접근성 관련 테스트 원칙 및 도구