74: Accessibility, part 1

그루두·2024년 7월 23일
0

100 days of SwiftUI

목록 보기
82/108

Project 15, part 1

VoiceOver를 위한 Image의 label 설정하기

먼저 이미지를 클릭하면 설정한 pictures 중 무작위로 선택된 이미지가 화면에 나타나는 코드가 있다.

// ...
    @State private var currentPicture = Int.random(in: 0..<4)
    var body: some View {
        Image(pictures[currentPicture])
            .resizable()
            .scaledToFit()
            .onTapGesture {
                currentPicture = Int.random(in: 0..<4)
            }
            .accessibilityLabel(labels[currentPicture])
            .accessibilityAddTraits(.isButton)
            .accessibilityRemoveTraits(.isImage)
    }
}

여기서 VoiceOver를 위해 각 이미지마다 설명을 문자열 배열인 labels의 해당 인덱스로 accessibilityLabel에 전달한다. 그리고 해당 view는 Image이지만 onTapGesture로 버튼의 역할을 부여했기에 .accessibilityAddTraits로 해당 사항을 설정할 수 있다.

Image(pictures[currentPicture])
            .resizable()
            .scaledToFit()
            .onTapGesture {
                currentPicture = Int.random(in: 0..<4)
            }
          .accessibilityLabel(labels[currentPicture])
            .accessibilityAddTraits(.isButton)
            .accessibilityRemoveTraits(.isImage)

깃헙 링크

위 코드처럼 Traits를 설정하기 보단 더 간단하게 버튼의 label로 Image를 설정해서 구현할 수 있다.

    var body: some View {
        Button(action: {
            currentPicture = Int.random(in: 0..<4)
        }, label: {
            Image(pictures[currentPicture])
                .resizable()
                .scaledToFit()
        })
        .accessibilityLabel(labels[currentPicture])
        .accessibilityAddTraits(.isButton)
        .accessibilityRemoveTraits(.isImage)
    }

깃헙 링크

데이터를 숨기거나 그룹으로 설정하기

가끔 이미지가 더 나은 UI를 위한 시각 자료(bullet point, 로고의 애니메이션)일 때가 있다. 이때는 accessibility를 위해 VoiceOver에서 감추는 것이 좋다.

Image(decorative: "ales-krivec-15949")

혹은,

Image("ales-krivec-15949")
	.accessibilityHidden(true)

그리고 텍스트가 Stack 안에 함께 있어도 끊겨져서 읽히는데, 한 문장으로 읽히도록 설정할 수 있다.

        VStack {
            Text("Hello this is")
            Text("A TEXT")
                .font(.title)
        }
        .accessibilityElement(children: .combine)

accessibilityElement의 기본 값은 .ignore로, 아래처럼 설정해도 된다.

        VStack {
            Text("Hello this is")
            Text("A TEXT")
                .font(.title)
        }
        .accessibilityElement()
        .accessibilityLabel("Hello this is a text")

깃헙 링크

💡 .accessibilityElement는 view들을 숨기는 것이 아니라 상위 view 하나로 읽히도록 설정한다.

.accessibilityAdjustableAction()로 VoiceOver 동작 설정하기

.accessibilityValue()로 해당 값을 label로부터 분리할 수 있다. 그리고 .accessibilityAdjustableAction()로 swipe 동작을 설정할 수 있다.

예시로 Increment 버튼을 누르면 value의 값이 1 증가하고 Decrement 버튼을 누르면 1 감소하는 기능이 있다.

        VStack {
            Text("value: \(value)")
            Button("Increment") {
                value += 1
            }
            Button("Decrement") {
                value -= 1
            }
        }
        .accessibilityElement()
        .accessibilityLabel("Value")
        .accessibilityValue(String(value))
        .accessibilityAdjustableAction { direction in
            switch direction {
            case .increment:
                value += 1
            case .decrement:
                value -= 1
            default:
                print("not handled")
            }
        }

깃헙 링크

  • 이를 .accessibilityElement()로 label 자체로 읽지 않게 설정하고
  • .accessibilityLabel()로 "Value"로 읽게 설정한다.
  • 그리고 .accessibilityValue()에 Value를 전달하여 value 값을 읽게 한다.
  • 마지막으로 .accessibilityAdjustableAction()으로 제스쳐의 방향에 따라 명령을 설정한다.

💡 default로 모르는 때를 대비하는 것이 좋다.

VoiceOver 작동 영상
https://github.com/treesofgroo/SwiftUI-with-HWS/commit/727c592095719f5b5c8bfd283e9b087e7f61f62c

profile
계속 해보자

0개의 댓글

관련 채용 정보