iOS 접근성 (SwiftUI)
[iOS - SwiftUI] Voice Over 접근성 - 우선순위 처리 방법(accessibilitySortPriority), 그룹화 방법 (accessibilityElement)
jake-kim
2024. 10. 16. 01:56
우선순위 처리 방법
- 보통 OS에서 왼쪽 상단에서 시작하여 오른쪽을 읽고 아래로 순차적으로 읽어줌
- 지구본의 이미지 -> Hello, world! -> toggle button
ex)
- Hello, world!가 가장 중요할 때, Hello, world!를 가장 먼저 읽히게 하고 싶은 경우?
- 해당 뷰에 accessibilitySortPriority를 높게 설정하기 (값이 높을수록 가장 먼저 읽힘)
- 따로 이 값을 설정 안하면 디폴트 값은 0
ex) "Hello, world!" 뷰를 accessibilitySortPriority를 1로 설정
struct ContentView: View {
@State private var toggle = true
var body: some View {
VStack {
HStack {
if toggle {
Image(systemName: "globe")
.resizable()
.frame(width: 24, height: 24)
}
Text("Hello, world!")
.accessibilitySortPriority(1) // <-
}
Button {
toggle.toggle()
} label: {
Text("toggle button")
}
}
.padding()
}
}
결과)
- 여기서 알 수 있는 것
- accessibilitySortPriority값이 동일하면 가로로 나열된 뷰(지구본 Image)를 하단에 있는 toggle button보다 먼저 접근성 동작
그룹화 방법
- 지구본과 "Hello, world!" 텍스트는 하나의 컴포넌트로 취급하기 위해서는 그룹화가 필요
- accessibilityElement(children:)을 사용
- 뷰를 접근성 컨테이너로 만들어주는 기능
- 이 API에서 가장 중요한 것은 children 인수 값
- 디폴트 값은 ignore이며 3가지 옵션이 존재
- 3가지 옵션
- ignore
- 마치 하나의 뷰처럼 합침 (A뷰, B뷰가 있을 때 이 2개의 뷰를 마치 하나의 뷰로 접근성에서 포커싱 됨)
- children 뷰들의 접근성 요소들을 모두 무시 (accessibilityTraits, accessibilityLabel 모두 초기화되어 새로 accessibilityLabel를 지정해줘야함)
- combine
- 마치 하나의 뷰처럼 합침
- children 뷰들의 접근성을 고려 (accessibilityLabel가 자동으로 내부에 있는 뷰 기준으로 입력됨)
- contain
- 접근성 포커싱 영역은 위 두 옵션과는 다르게 개별적으로 포커싱되지만 뷰가 여러개 있을 때 이 뷰들을 그룹화하고 그룹별로 순서를 주고 싶을때 사용
- ignore
ex) contain 사용 예시
- 상위에 HStack, 하위에 VStack으로 데이터가 있는 뷰에서 상위 HStack을 그룹화하여 먼저 읽히고 "Usres"라는 accessibilityLabel이 읽히도록 하고 싶은 경우 사용
var body: some View {
ScrollView {
VStack {
HStack {
ForEach(users) { user in
UserCell(user)
}
}
.accessibilityElement(children: .contain)
.accessibilityLabel("Users")
VStack {
ForEach(messages) { message in
MessageCell(message)
}
}
.accessibilityElement(children: .contain)
.accessibilityLabel("Messages")
}
}
}
- 다시 돌아와서, 아래 뷰 지구본과 "Hello, world!" 텍스트를 하나의 뷰로 묶고 싶은 경우?
- accessibilityElement(children: .combine) 사용하여 해결
HStack {
if toggle {
Image(systemName: "globe")
.resizable()
.frame(width: 24, height: 24)
}
Text("Hello, world!")
.accessibilitySortPriority(1)
}
.accessibilityElement(children: .combine)
결과)
- 지구본 이미지와 텍스트가 하나로 묶였고, "Hello, world!"라고 Text의 접근성 값도 자동으로 적용됨
- 주의사항)
- children옵션 중에서 ignore도 하나로 합쳐주지만, children 뷰들의 접근성 요소들을 모두 무시되므로 "Hello, world!"문구를 읽어주지 않기 때문에 따로 accessibilityLabel() 값을 추가해야함
ex) ignore을 사용한 경우
HStack {
if toggle {
Image(systemName: "globe")
.resizable()
.frame(width: 24, height: 24)
}
Text("Hello, world!")
.accessibilitySortPriority(1)
}
.accessibilityElement(children: .ignore)
결과) children 뷰들의 접근성 요소들을 모두 무시되므로 "Hello, world!"문구를 읽어주지 않음
* 전체 코드
import SwiftUI
struct ContentView: View {
@State private var toggle = true
var body: some View {
VStack {
HStack {
if toggle {
Image(systemName: "globe")
.resizable()
.frame(width: 24, height: 24)
}
Text("Hello, world!")
.accessibilitySortPriority(1)
}
.accessibilityElement(children: .combine)
Button {
toggle.toggle()
} label: {
Text("toggle button")
}
}
}
}
#Preview {
ContentView()
}
* 참고
- https://developer.apple.com/documentation/swiftui/view/accessibilityelement(children:)
- https://developer.apple.com/documentation/swiftui/view/accessibilitysortpriority(_:)