見出し画像

Now in REALITY Tech #100 Human Interface Guidelines勉強会とアクセシビリティの話

はじめに

こんにちは!REALITYでiOSエンジニアをしているharunaです。最近はiOSチーム内でお菓子作りがブームになっており、私も便乗した結果、家にチョコレートが500g余っていて消費に悩んでいます。
今回は社内で始めたHuman Interface Guidelines勉強会の話と勉強会で触れたアクセビリティの話について書きたいと思います。


Human Interface Guidelines勉強会を始めました!

REALITYではHuman Interface Guidelines (HIG)の勉強会を始めました!
HIGは、Appleが定めたガイドラインで、Apple製品を使うユーザーにとって、使いやすく、理解しやすいアプリを設計するためのデザインのルールが記載されています。 勉強会にはiOSエンジニアやデザイナーだけでなく、Android, Unityエンジニアなど様々な人が参加しており、毎週読み合わせをし、REALITYのアプリに落とし込みながら議論をしています。

勉強会で明らかになった不具合の原因

経緯

勉強会で HIGのアクセシビリティの章を読み合わせしている時に私たちはあることに気がつきました。当時、REALITYアプリにはある不具合がありました。不具合というのは「視聴画面を開くと画面左側に影が現れる」というものです(現在は修正されています)。

試聴画面左側に影が出てしまう

原因

HIGのアクセシビリティの章には、Appleのデバイスに搭載されているアクセシビリティの機能や、アクセシビリティを担保したUI設計の方針などが記載されています。そして、この章を読み進める中で、上記の不具合がiPhoneの「ボタンの形」機能に起因していることに気づきました。「ボタンの形」機能を有効にすると、UI上のボタンに境界線や背景色の変更などの視覚的な変更が加えられ、より明確に識別できるようになります。この機能は、視覚情報の処理に困難を持つユーザーや、画面上の要素を区別しにくいユーザーにとって有用です。

左: 「ボタンの形」をOFFにした時 / 右:「ボタンの形」をONにした時

今回不具合が出た領域は、投げられたギフトをアニメーションするエリアです。そしてその不具合の原因は、アニメーションが終了して不透明度を0にする処理をボタン全体ではなく、ボタンの中の要素に適用させていたことでした。つまり、中の要素が透明状態でボタンが見えていないのにも関わらず、そこにボタンが存在しているとみなされていたのです。
そのため、ボタン自体にアニメーションの処理を適用させることで、この問題は解決されました。

ギフトが表示されている様子
// BEFORE: Animation終了後、中の要素だけ透明になり、ボタン自体は画面上に存在しているとみなされる
Button {
    vm.tapped()
} label: {
    HStack(spacing: -78.0) {
        giftInfo
        giftImage
    }
    .opacity(opacity)
    .offset(x: offsetX, y: offsetY)
}

// AFTER: Animation終了後、Button自体が透明になり画面上からもボタンとみなされない
Button {
    vm.tapped()
} label: {
    HStack(spacing: -78.0) {
        giftInfo
        giftImage
    }
}
.opacity(opacity)
.offset(x: offsetX, y: offsetY)

HIG勉強会でアクセシビリティについて触れたことが、この不具合の解決策を見出すきっかけとなりました。また、単に直面した不具合を解決するだけでなく、アクセシビリティを考慮した設計の重要性も浮き彫りにしてくれました。

アクセシビリティ機能とカスタマイズ

VoiceOver

「ボタンの形」以外にも、Appleのデバイスには様々なアクセシビリティ機能があります。有名なところでいえば「VoiceOver」が挙げられます。これは画面上に表示されているテキスト、ボタン、アイコンなどの要素を音声で読み上げてくれる機能です。主に視覚障がいのあるユーザーがデバイスを使いやすくするためのアクセシビリティ機能です。
Swiftでは、accessibilityLabelのようなプロパティを使用して、視覚的要素に音声での説明を追加することができます。

class ViewController: UIViewController {
    @IBOutlet private var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
                // VoiceOver機能によって、選択されると読み上げが行われる
        label.accessibilityLabel = "これはラベルです"
    }
}

Dynamic Type

また、システム全体のテキストサイズを調整できる「Dynamic Type」という機能もあります。ユーザーが設定でテキストサイズを変更した場合、アプリ内のテキストもそれに応じてサイズを変更するのが好ましいです。Swiftでは、UIApplication.shared.preferredContentSizeCategory で現在の値を取得することができ、さらにUIContentSizeCategory.didChangeNotificationによって、テキストサイズの変更を監視し、その変更に応じてUIを再構成することができます。

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(handleContentSizeChange(notification:)),
                                               name: UIContentSizeCategory.didChangeNotification,
                                               object: nil)
    }

    @objc func handleContentSizeChange(notification: Notification) {
        updateUIForContentSizeChange()
    }

    func updateUIForContentSizeChange() {
        // 文字サイズ変更に応じたUIの更新処理をここに記述
        print("Dynamic Typeが変更されました。")
    }
}

これらのように、Appleのデバイスには様々なアクセシビリティ機能があり、それらをカスタマイズすることも可能です。すべてのユーザーが等しくREALITYアプリを楽しむために、アクセシビリティについてもこれから目を向けていきたいという気持ちが強くなりました!

まとめ

始まったばかりのHIG勉強会ですが、日々学ぶことが多く、意義ある時間を過ごせています!この学びを活かして、より一層快適にREALITYアプリを使えるように努めていきたいですね!