Android SeekBar 위젯 접근성 적용하기 1부, SeekBar 값 조절 접근성 문제 해결하기
안녕하세요, 엔비전스입니다.
Android에서 SeekBar 클래스는 미디어플레이어 뿐만 아니라 알람 볼륨 조절 및 여러 슬라이더에서 많이 사용됩니다. 이번 아티클에서는 SeekBar 구현 시 접근성 이슈와 고려해야 할 사항에 대해 준비해 보았습니다.
TalkBack에서 지원하는 SeekBar 클래스의 제스처
일반적으로 TalkBack과 같은 보조기술을 사용하지 않는 사용자는 SeekBar 클래스가 적용된 슬라이더를 조절하기 위해 핸들을 누르고 원하는 지점까지 드래그하거나, 원하는 부분을 터치합니다.
그러나 보조기술을 사용하는 사용자의 경우에는 상황에 따라 터치한 상태로 드래그하는 동작이 어려울 수 있습니다. 그래서 TalkBack의 경우에는 스마트폰의 볼륨키를 사용하여 값을 조절할 수 있도록 지원하고 있습니다. 사용자가 볼륨 키를 누를 때마다 값이 약 5퍼센트씩 증가 혹은 감소합니다. 따라서 SeekBar 요소에 포커스 하고 있으면 ‘값을 조절하려면 볼륨키를 사용하세요’라는 힌트 메시지도 출력합니다. 그뿐만 아니라 미세한 퍼센트 조정을 지원하기 위해 퍼센트를 숫자로 입력하여 해당 퍼센트로 이동해 주는 기능도 지원합니다. 마지막으로 블루투스 키보드와 같은 하드웨어 키보드를 연결할 경우 슬라이더에 포커스 한 상태로 오른쪽, 왼쪽 화살표 키를 이용하여 퍼센트 조절이 가능하기도 합니다.
SeekBar 접근성 오류 1: 볼륨 키로 값 조절해도 적용 안 되는 경우
하지만 특정 SeekBar에서는 TalkBack에서 지원하는 제스처로는 값 조절이 안 되는 경우가 있습니다. 예를 들어 사용자가 1퍼센트 증가시키면 일정 음량을 증가시키라는 이벤트가 구현되어 있다고 가정해 봅시다. 사용자가 터치한 상태로 드래그하는 동작을 해서 5퍼센트를 올리면 음량이 5퍼센트 수치 만큼 증가하는데 볼륨키를 이용해서 5퍼센트를 증가시키면 숫자만 증가했을 뿐 음량 값은 원래대로 있는 것입니다. 해당 원인은 사실 간단합니다. 터치 드래그 동작으로 SeekBar 슬라이더를 조절했을 때에만 이벤트가 발생될 수 있도록 구현했기 때문입니다.
SeekBar 이벤트를 구현할 때는 3개의 메소드를 사용합니다.
- 퍼센트가 변경될 때(onProgressChanged).
- 사용자가 터치 동작을 실행할 때(onStartTrackingTouch).
- 사용자가 터치 동작을 종료할 때(onStopTrackingTouch).
만약 퍼센트가 변경될 때 음량이 증가 혹은 감소하도록 이벤트를 구현했다면 아무런 문제가 없지만 반드시 터치 동작을 시작할 때 혹은 종료할 때 음량이 증가, 감소하도록 이벤트를 구현했다면 볼륨 키 혹은 하드웨어 키보드 동작은 터치 제스처가 아니므로 실제 값이 변경되지 않습니다. 그래서 가장 간단한 해결책은 이벤트를 구현할 때 터치가 시작되거나 종료될 때 구현되게 하지 말고 터치 동작이든 다른 동작이든 퍼센트를 변경하면 무조건 이벤트를 실행하게 구현하는 것입니다.
그러나 기획자의 의도에 따라 이 해결 방법은 적용하기 어려울 수 있습니다. 왜냐하면 터치를 한 상태에서 값을 조절하고 손가락을 떼기까지는 이벤트가 발생되지 않도록 구현하고 싶을 수도 있기 때문입니다. 그렇게 하지 않으면 터치한 상태라 하더라도 퍼센트를 조절할 때마다 수시로 값이 변경될 것입니다. 이런 경우 우리는 터치로 슬라이더를 조절하는 사용자와 TalkBack으로 조절하는 사용자 그룹을 다 만족시켜야 합니다. 따라서 터치 동작으로 값을 조절할 때는 터치를 끝낸 후 즉 손가락을 땠을 때만 최종적으로 이벤트를 발생시키고 TalkBack으로 볼륨키를 조절하면 퍼센트가 변경되는 즉시 무조건 이벤트가 발생하도록 해야 하는 것입니다.
대안 1: AccessibilityManager class 사용
안드로이드 접근성 서비스를 컨트롤할 때 주로 사용하는 클래스로 AccessibilityManager class에 대해서는 두 차례에 걸쳐 이미 다루었습니다. 이 클래스를 이용하면 미디어 플레이어 화면이 실행될 때 접근성 서비스가 켜져 있으면 단순히 사용자가 퍼센트 값을 변경하더라도 이에 대한 이벤트를 발생시키도록 구현하는 방법입니다.
예시:
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
value1 = i;
value2 = b;
if (accessibilityManager.isEnabled()) {
if(mPlayer!=null && value2){
mPlayer.seekTo(value1*1000);
}
}
}
대안 2: performAccessibilityAction 메소드 오버라이드 하기
안드로이드에서 버튼, 체크박스, 편집창, SeekBar와 같은 여러 위젯은 접근성 액션을 가지고 있습니다. 예를 들어 힌트 메시지 읽기를 오프로 설정하지 않았다면 버튼 요소에 포커스 하면 TalkBack은 어김없이 ‘활성화하려면 두 번 탭 하세요.’ 라는 힌트 메시지를 발화합니다. 이것은 접근성 정보를 담고 있는 AccessibilityNodeInfo에 클릭 액션이 포함되어 있다는 뜻입니다. 마찬가지로 편집창에 포커스 하면 두 개의 힌트 메시지를 발화합니다.
- 활성화하려면 두 번 탭 하세요.
- 두 번 탭하고 길게 누르세요.
이것은 편집창, 즉 EditText 위젯에는 클릭과 롱 클릭 두 개의 접근성 액션이 포함되어 있다는 뜻입니다.
SeekBar에 포커스 했을 때에는 클릭, 롱클릭 접근성 액션은 없고 scrollForward, scrollBackward 액션만 있습니다. 따라서 힌트 메시지 역시 ‘볼륨 키를 이용하여 조정하세요.’라는 메시지만 출력하고 클릭, 롱 클릭에 대한 힌트 메시지는 없습니다.
기본적으로 모든 접근성 액션은 각 위젯의 일반 액션으로 구현된 액션들을 그대로 가지고 옵니다. 그래서 일반적으로는 performAccessibilityAction을 만질 필요가 없습니다. 그러나 위에서 예로 든 SeekBar와 같은 경우에는 기본 스크롤 동작을 막아버렸으므로 접근성 액션을 통한 스크롤을 수행했을 때는 터치를 하지 않았더라도 변경된 값에 대한 이벤트를 적용하라는 명령을 주어야 합니다. 이때 사용하는 것이 바로 performAccessibilityAction입니다.
performAccessibilityAction은 위젯 객체 안에 setAccessibilityDelegate 객체를 만들고 그 하위에서 적용이 가능합니다. 아래 예시처럼 적용할 수 있습니다.
mSeekBar.setAccessibilityDelegate(new View.AccessibilityDelegate() {
@Override
public boolean performAccessibilityAction(View host, int action, Bundle args) {
switch (action) {
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
볼륨 키를 눌렀을 때 퍼센트가 증가되도록 하는 메소드 추가
}
}
return super.performAccessibilityAction(host, action, args);
}
});
결론
지금까지 SeekBar 구현 시 가장 치명적인 접근성 이슈와 이에 대한 해결방안을 살펴보았습니다. 개인적으로 저는 SeekBar의 접근성 적용을 위해 performAccessibilityAction 메소드 보다는 AccessibilityManager 클래스를 사용한 구현을 더 선호합니다. 이는 performAccessibilityAction을 통해 구현할 경우 키보드 이벤트, 즉 오른쪽/왼쪽 화살표를 눌렀을 때에도 슬라이더 조절이 가능하도록 하는 이벤트를 따로 구현해야 하기 때문입니다. 그러나 이것은 하나의 개인적인 의견임을 밝혀 둡니다. 중요한 것은 어떻게 구현하든 SeekBar를 보조기술을 사용해서도 슬라이더를 사용자가 원하는 대로 조절할 수 있도록 구현해 주는 것입니다.
다음 섹션에서 이어집니다.