アプリを視覚的にアクセシブルにする – WWDC2020

Session概要

アクセシビリティを考慮にいれたデザインをすると、アプリを使う人全員にパワーを与えることができます。アプリに適応性の高いインタフェースを作り、思慮深いアプローチから色を選び、読みやすいテキストを提供し、全体に優れた体験を提供できるような視覚的設定を採用する方法について https://developer.apple.com/videos/play/wwdc2020/10020/

視力喪失について

視力喪失の種類について

  • 視力喪失には様々な程度があり、人によって経験する症状に違いがあります
    • 完全に見える人もいれば、弱視、盲目の人など
  • その他、色覚異常光感受性などの症状がある
    • 色覚異常
      • 正常とされる他の大勢の人とは色が異なって見えてしまう・感じてしまう状態のこと
    • 光感受性
      • 最小量の光(最小光)を感じる視覚機能、および光の強さの最小量の違い(明暗差)を感じる視覚機能
iOSで設定可能なビジュアルに関する設定について

色とシェイプを活用したアプリのブランディング

色のみでコンテンツの差別化をしている
色とシェイプにより差別化をしている

  • アプリの特定のUI要素を目立たせたい場合、色を使って強調するだけでは色覚異常や停止力の人にとって強調された部分を判別しにくいです
  • そのため、優れたデザインにするためにはシェイプを使用する
    • ボタンの形やサイズを変更することでさらなる可視化を実現する
    • ボタンの形をデフォルト設定に適用できない場合は、ボタンシェイプ設定を有効にし、別の外観を用意する
    • 設定を確認するには、 UIAccessibilityでbuttonShapesEnabled(iOS 14から利用可能)を呼び出す
    • または、buttonShapesEnabledStatusDidChangeNotification(iOS 14から利用可能) を監視して、設定が変更された際にアプリ実行中でも変更処理を行うようにする
  • iOS 13から導入されたDifferentiate Without Color(カラー以外の区別)設定を適用することでボタン以外でも表示の差別化ができる
    • これは色だけを頼りにした要素の表示にも適応すべき
  • 視覚アクセシビリティ対応を検討する時期は開発の初期がベスト
  • 色の対比によっては、可視性が悪い組み合わせがある
    • Increase Contrastのアクセシビリティ設定では、色の対比を強調し、各要素を目立たせる
    • iOSが提供する幅広い種類のシステムカラーは、Increase Contrastの設定などに自動適用される
    • ライトモードでは少し暗く、ダークモードでは少し明るく表示されるようになり、コントラストが高まる
    • Xcodeのアセットカタログでは、Attributes Inspectorで変更を行い、シンボルの外観を設定可能
      • Appearancesで High Contrastに設定すると、シンボルの別バージョンが表示される
    • Color Contrast Calculatorを使用して、2つの色のコントラストを計算する
  • Smart Invert Colorsはダークモードに似た機能で、明るい白色のUI要素を暗くします
    • Smart Invert Colorsは、アプリUIを反転表示する設定
      • そのため、写真やビデオ、アプリアイコンなどは反転されないようにフラグをつける
      • UIViewサブクラスでaccessibilityIgnoresInvertColorsを設定すれば可能
    • Smart Invert Colorsではダークモードよりコントラストが高くなるため、光感受性者はこちらを好むでしょう

High Contrast Setting
Color Contrast Calculator
// Button Shapes
func observeButtonShapesNotification() {
    // Make buttons more visible by using shapes.
    // If your default design does not include button shapes, observe this notification to make visual changes.
    NotificationCenter.default.addObserver(self, selector: #selector(updateButtonShapes), name: UIAccessibility.buttonShapesEnabledStatusDidChangeNotification, object: nil)
}

@objc func updateButtonShapes() {
    if UIAccessibility.buttonShapesEnabled {
        // Use extra visualizations for buttons.
    } else {
        // Use default design for buttons.
    }
}

// Differentiate Without Color
func observeDifferentiateWithoutColorNotification() {
    // Use symbols or shapes to convey meaning instead of relying on color alone.
    // If your default design does not differentiate without color, observe this notification to make visual changes.
    NotificationCenter.default.addObserver(self, selector: #selector(updateColorAndSymbols), name: NSNotification.Name(UIAccessibility.differentiateWithoutColorDidChangeNotification), object: nil)
}

@objc func updateColorAndSymbols() {
    if UIAccessibility.shouldDifferentiateWithoutColor {
        // Use symbols or shapes to convey meaning.
    } else {
        // Use default design.
    }
}

// Smart Invert Colors
extension UIView {
    @available(iOS 11.0, tvOS 11.0)
    var accessibilityIgnoresInvertColors: Bool { get set }
}

テキストの読みやすさについて

  • アプリデザインでは、文字をくっきりと読みやすくするよう留意する

Bold設定と活用したテキストの強調デザイン
// 大きなテキストの設定
// 画面上で表示が調整されると呼び出される
override func traitCollectionDidChange (_ previousTraitCollection: UITraitCollection?) {

     if (traitCollection.preferredContentSizeCategory       
         < .accessibilityMedium) { // Default font sizes

         stackView.axis = .horizontal
         stackView.alignment = .center

     } else { // Accessibility font sizes

         // ディスプレイの幅を最大限利用したラベル表示が可能
         stackView.axis = .vertical
         stackView.alignment = .leading

     }
}

// 太文字の設定
func observeBoldTextNotification() {
    // Update labels to use bold or heavy font styles.
    // If you aren't using system font styles, observe this notification to make visual changes.
    NotificationCenter.default.addObserver(self, selector: #selector(updateLabelWeight), name: UIAccessibility.boldTextStatusDidChangeNotification, object: nil)
}

@objc func updateLabelWeight() {
    if UIAccessibility.isBoldTextEnabled {
        // Use bold or heavy font weight
    } else {
        // Use font weight that is default to your design.
    }
}

表示設定変更によるアプリの外観変更

  • アプリに視差効果(UIMotionEffect)を実装した場合におけるユーザへの配慮
    • 乗り物酔いのような状態となるユーザもいるため、画面の動きに敏感な人向けの表示設定を行う
    • 下記設定から、アイドルアニメーションや視差効果の動作、動画の自動再生、GIFなども抑制が可能
    • UIAccessibilityでisReduceMotionEnabledを設定する
    • reduceMotionStatusDidChangeNotificationで設定変更を確認する
  • PreferCrossFadeTransitions
    • 画面遷移時のアニメーションをフェードイン・フェードアウトのみに変更可能
  • Reduced Transparency(透明度の低下)設定
    • ぼやけた背景を不透明にする機能で、ぼかしの濃淡を均一にする
    • ぼやけた背景ではコントラストが乱れ可読性が下がることや、ユーザによってはめまいが生じる可能性があるため

モーションエフェクトを抑制する設定
// モーションエフェクトの抑制
func observeReduceMotionNotification() {
    // Observe this notification to reduce or remove the frequency and intensity of motion effects.
    NotificationCenter.default.addObserver(self, selector: #selector(updateMotionEffects), name: UIAccessibility.reduceMotionStatusDidChangeNotification, object: nil)
}

@objc func updateMotionEffects() {
    if UIAccessibility.isReduceMotionEnabled {
        // Reduce or remove extraneous motion effects.
    } else {
        // Use default motion effects.
    }
}
// Prefer cross fade transitionsの実装
func observeCrossFadeTransitionsNotification() {
    // Reduce or remove sliding animations for transitioning views.
    // If you aren't using system-provided navigation, observe this notification to make visual changes.
    NotificationCenter.default.addObserver(self, selector: #selector(updateTransitionEffects), name: UIAccessibility.prefersCrossFadeTransitionsStatusDidChange, object: nil)
}

@objc func updateTransitionEffects() {
    if UIAccessibility.prefersCrossFadeTransitions {
        // Replace sliding transitions with cross-fade animations.
    } else {
        // Use default sliding transitions.
    }
}
// Reduce Transparencyの設定通知実装
func observeReduceTransparencyNotification() {
    // Reduce or remove transparency by adjusting these effects to be completely opaque.
    // If you aren't using system-provided visual effects for blurs or vibrancy, observe this notification to make visual changes.
    NotificationCenter.default.addObserver(self, selector: #selector(updateTransparencyEffects), name: UIAccessibility.reduceTransparencyStatusDidChangeNotification, object: nil)
}

@objc func updateTransparencyEffects() {
    if UIAccessibility.isReduceTransparencyEnabled {
        // Make transparency effects opaque.
    } else {
        // Use default transparency.
    }
}
最新情報をチェックしよう!