-
iOS - 접근성, Voice over, custom UIAccessibilityElementios 2023. 3. 15. 12:20
iOS 앱 접근성 관련 작업을 하게 됐다.
voice over 기능 사용 중에 한하여, element에 포커스와 탭 이벤트 발생 시 별도의 기능을 구현하고자 했다.
View의 accessibilityElements에 accessibilityCustomActions 을 설정해 해결하고자 했지만,
아래와 같은 문제를 만났다.
- custom action의 존재 유무가 voice over로 잘 나타나지 않았다.
- custom action을 사용하기 위해, 포커스가 해당 element로 이동 후, '한 손가락으로 아래 스와이프' 후 더블탭을 해야했다.
결국 유저 입장에서 custom action 안내를 받지 못하며, 사용을 위해 추가 동작까지 필요했다.하여 UIAccessiblityElement를 상속하는 커스텀 클래스를 만들어, 포커스와 탭 이벤트 관련 메소드를 override 했다.
class SomeAccessibilityElement: UIAccessibilityElement { // weak var delegate: SomeDelegate? private let _name: String init(name: String, accessibilityContainer: Any) { self._name = name super.init(accessibilityContainer: accessibilityContainer) self.isAccessibilityElement = true self.accessibilityTraits = [.button] self.accessibilityLabel = name } override func accessibilityActivate() -> Bool { // delegate?.didTapped(sender: _name) print("선택 시 호출, voice over double tap") return true } override func accessibilityElementDidBecomeFocused() { // delegate?.didBecomeFocused(sender: _name) print("포커스 될 시 호출") } }
처리는 ViewController 에서 하기 위해 delegate 를 설정했는데 빙 돌아오는 것 같은 느낌이 들었다.
delegate를 제거할 방법을 찾게 되길..
스크롤뷰 화면 경우 포커스가 계속 이동해도 스크롤이 이동하지 않는 경우도 있음.
스크린 리더가 포커스 이동에 따른 화면 스크롤을 하지 않는다.
self.view 가 아닌 scrollView의 accessibilityElements에 요소들을 넣어줘야 한다.scrollView.accessibilityElements = scrollviewAccessibilityElements view.accessibilityElements = [ scrollView as Any ]
CollectionViewCell 접근성 적용의 경우,
cell에 접근 가능 설정할 시, cell 하위 ui 요소들이 접근 불가능한 문제 있었음.- cell 자체를 접근 활성화 하지 말고, 하위 요소들을 활성화 한다. isAccessibilityElement = true
이후 cell의 accessibilityElements 에 하위 요소들을 담아 parent child 관계 UI 들을 수평 accessibilityElements로 설정했다.https://stackoverflow.com/questions/56450485/uicollectionview-accessibility-focus
element에 focus 주기 위한 타입 메서드 익스텐션
extension UIAccessibility { /// object에 voice over 스크린 리더 focus 설정 static func setFocusTo(_ object: Any?, deadline: DispatchTime = .now() + 0.5) { if UIAccessibility.isVoiceOverRunning { DispatchQueue.main.asyncAfter(deadline: deadline) { UIAccessibility.post(notification: .layoutChanged, argument: object) } } } }
voice over 문구 출력 위한 익스텐션
extension UIAccessibility { /// voice over 안내 메시지 출력 static func announcement(_ text: String, deadline: DispatchTime = .now() + 0.1) { if UIAccessibility.isVoiceOverRunning { DispatchQueue.main.asyncAfter(deadline: deadline) { UIAccessibility.post(notification: .announcement, argument: text) } } } }
'ios' 카테고리의 다른 글
스토리보드 커스텀 폰트 이슈 - Xcode15 (0) 2023.10.23 iOS - SNS 간편 로그인 (네이버 간편 로그인, 네아로) 심사 리젝 reject (0) 2023.05.22 Swift / iOS앱 Tuist 적용기 (0) 2023.02.22 Compositional Layout, Unable to simultaneously satisfy constraints. (0) 2022.11.27 diffable datasource Error - Inconsistent associations for moves 에러 (0) 2022.11.26