Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 3. VoiceOver Accessibility (앱 접근성) - 적용 방법, 그룹핑 방법(UIAccessibilityElement) 본문

iOS 응용 (swift)

[iOS - swift] 3. VoiceOver Accessibility (앱 접근성) - 적용 방법, 그룹핑 방법(UIAccessibilityElement)

jake-kim 2023. 5. 18. 01:52

1. VoiceOver Accessibility (앱 접근성) - 개념

2. VoiceOver Accessibility (앱 접근성) - 주의사항, 시뮬레이터 Accessibility 테스트

3. VoiceOver Accessibility (앱 접근성) - 적용 방법, 그룹핑 방법(UIAccessibilityElement)

그룹화 방법

  • UIAccessibilityElement를 사용하면 디폴트인 왼쪽에서 오른쪽으로 변경이 가능

읽어주는 형태

ex) 뷰에 4개의 UILabel이 있고 각각 상단 하단에 있는 UILabel을 하나의 그룹으로 지정해서 접근성이 동작하도록 수정 방법?

  • 초기 코드
class ViewController: UIViewController {
    private let firstTopLabel: UILabel = {
        let label = UILabel()
        label.text = "title1"
        label.font = .systemFont(ofSize: 18, weight: .regular)
        label.numberOfLines = 0
        label.textAlignment = .center
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    private let firstBottomLabel: UILabel = {
        let label = UILabel()
        label.text = "desk1"
        label.font = .systemFont(ofSize: 18, weight: .regular)
        label.numberOfLines = 0
        label.textAlignment = .center
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    private let secondTopLabel: UILabel = {
        let label = UILabel()
        label.text = "title2"
        label.font = .systemFont(ofSize: 18, weight: .regular)
        label.numberOfLines = 0
        label.textAlignment = .center
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    private let secondBottomLabel: UILabel = {
        let label = UILabel()
        label.text = "desc2"
        label.font = .systemFont(ofSize: 18, weight: .regular)
        label.numberOfLines = 0
        label.textAlignment = .center
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        setupLayout()
    }
    
    private func setupLayout() {
        view.addSubview(firstTopLabel)
        view.addSubview(firstBottomLabel)
        view.addSubview(secondTopLabel)
        view.addSubview(secondBottomLabel)

        NSLayoutConstraint.activate([
            firstTopLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 120),
            firstTopLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            firstBottomLabel.topAnchor.constraint(equalTo: firstTopLabel.bottomAnchor),
            firstBottomLabel.leadingAnchor.constraint(equalTo: firstTopLabel.leadingAnchor)
        ])
        NSLayoutConstraint.activate([
            secondTopLabel.topAnchor.constraint(equalTo: firstTopLabel.topAnchor),
            secondTopLabel.leadingAnchor.constraint(equalTo: firstTopLabel.trailingAnchor, constant: 16),
            secondBottomLabel.topAnchor.constraint(equalTo: secondTopLabel.bottomAnchor),
            secondBottomLabel.leadingAnchor.constraint(equalTo: secondTopLabel.leadingAnchor),
        ])
    }
}
  • 1단계) 순서 바꾸기
    • as-is: title1 -> title2 -> desc1 -> desc2
    • to-be: title1 -> desc1 -> title2 -> desc2

  • 뷰가 가지고 있는 accessibilityElements에 UILabel의 순서를 넣어주면 완성
private func setupAccessibilityLabel() {
    var elements = [Any]()
    
    elements.append(firstTopLabel)
    elements.append(firstBottomLabel)

    elements.append(secondTopLabel)
    elements.append(secondBottomLabel)
    
    accessibilityElements = elements
}

* 주의) Simulator로 테스트하면 제대로 동작 안하므로 실물 디바이스로 테스트할것

순서 변경 완성

  • 2단계) UILabel 상단과 하단을 그룹핑하기 
    • UIAccessibilityElement가 하나의 group이 되며 여기에 상하 UILabel의 frame을 계산하여 넣어주면 하나의 접근성으로 동작
    • accessibilityFrameInContainerSpace에 두 개 UILabel 프레임을 대입하면 그룹핑 완료
// 그룹의 프레임 크기를 알아야하므로 viewDidAppear에서 아래 메소드 호출

private func setupAccessibilityLabel2() {
    var elements = [Any]()
    
    let group1 = UIAccessibilityElement(accessibilityContainer: self)
    group1.accessibilityLabel = "\(firstTopLabel.text!), \(firstBottomLabel.text!)"
    group1.accessibilityFrameInContainerSpace = firstTopLabel.frame.union(firstBottomLabel.frame)
    
    elements.append(group1)
    elements.append(firstTopLabel)
    elements.append(firstBottomLabel)
    
    let group2 = UIAccessibilityElement(accessibilityContainer: self)
    group2.accessibilityLabel = "\(secondTopLabel.text!), \(secondBottomLabel.text!)"
    group2.accessibilityFrameInContainerSpace = secondTopLabel.frame.union(secondBottomLabel.frame)

    elements.append(group2)
    elements.append(secondTopLabel)
    elements.append(secondBottomLabel)
    
    accessibilityElements = elements
}

UIAccessibilityElement로 그룹핑 완료

주의) UILabel 상단, 하단 각각 접근성을 제외하고 하나의 뷰처럼만 동작하게끔 할 경우, UIView로 두 개의 UILabel을 감싸는 커스텀 뷰가 필요하고 두 개의 UILabel의 isAccessibilityElement를 false로 처리해야함

 

* 전체 코드: https://github.com/JK0369/ExVoiceOverGrouping

* 참고

https://developer.apple.com/documentation/uikit/uiaccessibilityelement

Comments