ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
SwiftUIにおけるアクセシビリティの最新情報
SwiftUIを使用すると、高品質で、あらゆる人がアクセスしやすいアプリ体験をより簡単に構築できます。このセッションでは、SwiftUIが提供する充実したアクセシビリティ要素を通じて、補助機能のテクノロジーがどのようにアプリを理解してナビゲートするかについて説明します。また、アクセシビリティの修飾子を使用して、アプリのコンテンツとインタラクションに関するより多くの情報を提供し、ユーザーの利用体験をさらにカスタマイズする方法も取り上げます。
関連する章
- 0:00 - Introduction
- 0:58 - Fundamentals
- 9:01 - View accessibility
- 16:28 - Enhanced interactions
リソース
-
ダウンロード
こんにちは アクセシビリティチーム エンジニアのTommyです 優れたアプリには アクセシビリティが欠かせません その体験を通じて誰もが創造性を発揮し つながり 楽しめるようにするためです SwiftUIは すべてのAppleプラットフォームで こうした体験の実現を可能にします 今日はSwiftUIに組み込まれている すぐに使えるアクセシビリティ機能と アプリのアクセシビリティの調整や 作成に役立つツールを紹介します
次に SwiftUIに詳しい情報を提供して ビューのアクセシビリティを 改善するべき場所について説明します
最後に タップ ドラッグ ドロップなどの アクセシブルでリッチな 操作のビルド方法を紹介します
SwiftUIは組み込みビューの アクセシビリティに対応して ゼロから設計されており アクセシビリティ技術への情報の追加や アプリ体験の調整が容易です 私は 海を訪れた時の楽しい思い出を 共有するためのアプリを SwiftUIで開発しています このアプリでは 海の美しい景色を伝える メッセージを送ることができます タップするだけで 位置情報を追加したり 波の音を録音したり 評価を入力できるのです 誰でも旅行についてコメントできて お気に入りへの追加や メッセージへの返信も可能です
返信相手に応じてカスタムサウンドを 作成することもできます
ではここで SwiftUIを使って これらの機能をアクセシブルにする 方法を見てみましょう SwiftUIはアクセシビリティ要素を プライマリ出力の1つとして作成します アクセシビリティ要素は アプリのコンテンツを ユーザーに届けるための 基本的な構成要素であり VoiceOver 音声コントロール スイッチコントロールなどの 技術に使用されています アクセシビリティ要素とは 1つ以上のビューのことです ビューの内容を説明する属性と ビューを操作するための タップや複雑な仕草などの アクションを提供します
VoiceOverなどのアクセシビリティ技術は 要素を通じてのみ アプリとやり取りするので ビューから提供され要素に含まれている コンテンツだけにアクセスできます
これはトグルビューです 私が投稿した旅行に 友だちからの コメントを許可するかどうか設定できます
トグルはビュー本文で宣言されており SwiftUIはこれを使って 出力を形成します 例えば 画面の表示内容や アクセシビリティ要素についてなどです
アクセシビリティ要素では Commentsラベルを使って 要素のラベルを作成します 適用される特性は isToggleとisSelectedです 設定の切替には pressアクションを使用します
VoiceOverがこのトグルにフォーカスすると 要素が説明され ダブルタップすることで pressアクションを実行できます 「設定 見出し コメント 切り替えボタンオフ オン」
SwiftUIは テキストとトグルを組み合わせて 単一の要素に落とし込みます 複数のビューを単一の要素で表すことにより ナビゲーションを簡素化して 関連情報をつなぎ合わせることができます アプリにあわせてトグルの見た目や 印象をカスタマイズする場合は 要素の属性とアクションを 保存することが重要です SwiftUIの強力な ビュースタイリングシステムは 組み込みのアクセシビリティ機能を失わずに ビューの外観を変更できます
属性とアクションは ビューの見た目や スタイルが変更されても適用されます
トグルスタイルの修飾子(モディファイア) でスタイルを変更すると トグルの見た目が変わりますが 要素のラベルと特性は保持されます
カスタムトグルがタップされると 要素の属性にトグルの 新しい状態が反映されます
ビューのスタイルはボタンやトグルのほか ラベルやラベル付きコンテンツなどの グループ 進捗ビューやゲージなどの インジケータを含め 様々なコントロールでサポートされています 可能な限りカスタムビューではなく スタイリングシステムを使用してください そうしないと 自動的に付与された アクセシビリティプロパティを 再適用することになります スタイルと組み込みビューにより アプリのアクセシビリティの 体験が向上します しかし より多くのアクセシビリティ情報を SwiftUIに渡すことができれば 体験はさらに改善されます この情報はアクセシビリティ修飾子を 使って提供できます
アクセシビリティ修飾子により アクセシビリティ要素によるビューの 表示方法をカスタマイズできます ラベルや特性のような 属性もビューに追加できます カスタムジェスチャなどの操作用 アクションも公開できます
さらに 複数のビューを組み合わせて 単一の要素を構成し ナビゲーションを 向上させることもできます
修飾子を使用して ビューのアクセシビリティを カスタマイズする前に VoiceOverなどを使用して 改善の余地があるアプリ体験を 見つけることをお勧めします
このアプリでVoiceOverを使って 最近の海への旅行を確認し 改善点を見つけましょう
「週末の冒険 見出し」 「土曜日 素敵な週末でした 波は静かで 太陽は橋の上で輝き 空には雲ひとつ ありませんでした 画像」 「いい旅でしたね お気に入り ボタン 返信 ボタン Nick」
「本当にきれい お気に入り ボタン 返信 ボタン Jack」
SwiftUIで優れたアプリ体験を 作成できたようです VoiceOverはすべての コンテンツを読み上げ 見出しのインジケータや ボタンなども調整されていました 気づいた改善点が3つありました まず コメントセクションを読み上げる際 要素が多いため時間がかかりました 各コメントとボタンのつながりも わかりづらく混乱しました VoiceOverに読み上げられなかった ビューもありました たとえば未読インジケータなどです それでは この体験を より良くしていきましょう
これはコメントビューです 横方向に配置された要素は コメントのメッセージ 未読インジケータ お気に入りボタン 返信ボタンを表しています SwiftUIはこのビューに 3つの要素を作成します タイトルに1つと アクションのボタンに2つです スタックとスペーサビューは 要素ではなく ただビューのレイアウトを 調整するだけです デフォルトでは未読インジケータは シェイプビューとされており アクセシビリティ要素ではありません 最初に未読状態を説明する ラベルを追加しましょう
最初にアクセシビリティ ラベル修飾子は デフォルトでは存在しない インジケータ用の要素を作成してから ラベルを未読に設定します
インジケータビューが未読のときも 要素は常にアクセシビリティの 技術で可視化されます コメントを読むときも SwiftUIが役立ちます コメントが読まれるとインジケータの 不透明度がゼロになって 見えなくなります アクセシビリティ技術から エレメントを自動的に隠すことも SwiftUIなら可能です
コメントビューの移動を 簡易化するために各スタックを 単一の要素にして各ボタンを 要素のアクションにできます アクセシビリティ要素である children combine修飾子を適用することで 複数の要素の 属性とアクションが結合されます
要素のラベルはすべてのビューを 組み合わせたラベルになります 重要な特性は結合され ボタン等のコントロールからのアクションは カスタムアクションになります これで単一の要素がメッセージ 未読状態 アクションを表すようになり コメントの確認が ずっと簡単になりました 再び各コメントを VoiceOverで確認すると 理解しやすくなっています 「未読 いい旅でしたね Nick ボタン」 「お気に入り 返信」
SwiftUIのおかげでアクセシビリティが 大幅に向上しましたが コンテキストに沿った情報を もっと提供することで コンテンツを網羅した楽しい体験を 提供できるようになります 海の旅行に関する メッセージは改善できましたが 友達のコメントに もう少し手を入れましょう
私のアプリではお気に入りの コメントをダブルタップすると 「特にお気に入り」になります すると新しいマークが付いて そのコメントの価値を示すのですが この変更で新たな問題が発生します 先ほどまでは組み合わせたアクションで お気に入りを適切に ラベリングできていたのに 今回はVoiceOverが 記号を読み上げています 「未読 本当にきれい Jack ボタン」
「お気に入り」 「返信」 「未読 日焼け止めは 塗っていた? Beth ボタン」
「きらきら 返信」
通常 ビューで記号を使うと 星や矢印などの デフォルトのラベルが使用され 意味も推測される場合があります 他の記号を使う場合は 念のためにラベルを名前として 明示的に追加しておく必要があります デフォルトのラベルを使う場合でも アクセシビリティ技術を 使用したときにインターフェイスを 正確に説明できているか 注意しましょう 「特にお気に入り」の場合 光の記号の ラベルを正しく更新する必要があります
アクセシビリティラベルを修飾子で 追加すると 「特にお気に入り」でない メッセージに適用されたときに デフォルトの正しいSwiftUIを 上書きしてしまいます
iOS 18ではisEnabledパラメータを アクセシビリティ修飾子に追加できます この修飾子が有効になっていると 属性がビューに適用され そうでなければ この修飾子は 効果を発揮しません 「特にお気に入り」ラベルは コメントが「特にお気に入り」に なったときのみ適用され 単なるお気に入りでは SwiftUIは星記号の デフォルトのラベルに戻ります このようにSwiftUIはデフォルトで 適切なアクセシビリティを実現しますが 時には条件に応じて カスタマイズも必要です
アプリのコメントビューに戻ってみると 「特にお気に入り」アクションが復活し ラベルも問題ありません 「未読 日焼け止めは 塗っていた? Beth ボタン」 「特にお気に入り 返信」
ラベルなどの情報が欠落しているなら 必ず追加するべきですが 到達までに複数の操作が必要な 情報に アクセシビリティ技術で もっと簡単にアクセスさせられれば アプリの使用体験はさらに向上します これらの改善は ホバー キー押下 ジェスチャによって ビューが動的に表示される 場合に特に役立ちます 私はアプリをmacOSで 動かすつもりだったので ホバーで旅行の追加情報を 表示させようとしました
旅行の画像のビューに カーソルを置くと 場所 記録 海の評価などの 添付ボタンが表示されます これで画面がすっきりして きれいな海の写真に集中できますが 添付情報のアクセシビリティについて 数点考慮する必要があります ホバー可能なビューなどの 動的に表示されるコンテンツは アクセシビリティ技術や キーボード スイッチなどの 接触型の入力手段からアクセスするのに 時間がかかることがあります
カーソルを動かしてビューを 表示し操作するだけなら 数秒しかかかりません
しかしVoiceOverでは 多くのステップを踏む必要があります ホバー可能なビューに注目し コマンドでホバー機能を起動し ビューが表示されたらサブビューに移動し 操作に注目したら そのあとで元のビューに 戻る必要があります
この操作はホバー可能なビューの アクセシビリティの属性とアクションを メインビューの一部として 追加することで簡略化できます
記録や場所を添付しない 旅行も多いでしょうから 旅行に追加するアクションまたは ラベルの正確な数は変動します SwiftUIのアクセシビリティ修飾子は このようなときに便利です アクションから始めましょう
これは旅行のビューのホバー可能な オーバーレイです コントロールにアクセスしやすくするため これらをカスタムアクションとして 作り変えます
アクセシビリティのアクション修飾子により 添付情報にも同じビューを指定します コントロールを抽出して旅行のビューの カスタムアクションに作り変えるのです これで 旅行のビューの オーバーレイとカスタムアクションの ロジックが同じになりました この変更により VoiceOverは 現在のオーバーレイを示さなくても 各添付情報を示せるようになります
「土曜日 素敵な週末でした 波は静かで 太陽は橋の上で輝き 空には雲ひとつありませんでした 画像」 「アクションメニュー 2つのアイテム 場所 記録」
さて 海の評価についての情報が 抜けているようです 評価はホバーで表示されますが 重要な情報なので 旅行のアクセシビリティ要素でも もっと目立たせたいですね
重要な情報を出すのに 複数の操作が必要な場合は その情報を要素に追加して 表示されていなくても 移動しやすくするという 選択肢があります 複数の要素を組み合わせるなどで 要素の属性を 修正したのならコンテンツを 象徴する装飾ビューで コンテンツを追加すると よいでしょう
どちらの場合も動的な コンテンツを含むビューの ラベルを修正する必要があります SwiftUIにはこれらの処理に 対応したツールがあります
それでは旅行の 要素ラベルに評価を追加して 読み上げ時に見つけやすくしましょう
普通のラベル修飾子では SwiftUIが要素に提供した 説明内容が消えてしまいます また 評価の表示頻度は低いので 今回は一部のメッセージにのみ 評価の情報を入れ込むだけとします
アクセシビリティラベル修飾子は ビューにも使うことができ ビューのテキストを抽出して 旅行の要素ラベルに設定します プレースホルダも ビューの既存のラベルに 設定できるので 旅行の評価を SwiftUIが旅行の 要素用に作成した 既存のラベルに統合できます
評価と旅行の投稿が 単一のラベルになったので 旅行のビューではVoiceOverの 読み上げが適切に行われています 「星半分 土曜日 素敵な週末でした 波は静かで 太陽は橋の上で輝き 空には雲ひとつ ありませんでした 画像」
良さそうですね ホバーはAPIのユースケースとしては 初歩的なものです コンテンツの変更内容は 必ずVoiceOverなどの技術から アクセス可能にしましょう
アプリの操作性を 設計するときは タッチ操作や マウス以外の入力の快適性にも 配慮を忘れないでください
インタラクションの中でも 特に一般的に使用されているのが ドラッグ&ドロップです
VoiceOver 音声コントロールなどの 技術はこれにも対応しており SwiftUIではこのような体験を 「on drag」「on drop」修飾子で サポートしています
ドラッグ&ドロップは柔軟に設計できるため 複数の方法でアプリ体験を強化できます このアプリではコメントのカスタム通知を ドラッグ&ドロップで作成できます VoiceOverで試してみましょう 1人あたり最大3つまでサウンドを ドラッグして通知を作成できます カスタムドロップデリゲートで 複数のドロップポイントを 単一ビューに配置しているので VoiceOverは音を ドロップできる場所を知りません 「シンセ ドラッグ可能」 「ドラッグ」
「拍手 ドラッグ可能 通知 音なし」
「ドロップ ドロップ準備」 「ドロップ完了」
accessibilityDropPoint修飾子は ビュー上でドラッグ&ドロップ操作が 可能な場所を定義します コメント通知ビューには3つの ドロップポイントが定義されており アラートに設定できる3つの サウンドを説明しています 各ポイントには実行される 操作を説明するための ラベルも存在します これでVoiceOverが通知ビューの 各ドロップポイントにアクセスできます 「シンセ ドラッグ可能」 「ドラッグ」
「拍手 ドラッグ可能 通知 ベル 鳥」 「ドロップ ドロップ準備 サウンド3を設定 ドロップ準備」
「ドロップ完了」
体験が改善されたので アプリ内でサウンドをすばやく対象に ドラッグできるようになりました
ドラッグ&ドロップ体験を 構築するときは アクセシビリティ技術上でも 問題なく動作するか 必ず確かめることが重要です ドラッグ&ドロップに カスタムアクションを設定して ドラッグに目的地やアクションを 設定するのも良いでしょう
複数のポイントで複数の操作を サポートしている要素であれば 各ポイントがアクセシビリティ技術に 公開されているか確認してください 操作はアプリの外部の 操作ウィジェットに及ぶこともあります ウィジェットのビューは 更新速度が遅いので アクセシビリティアクションの修飾子が 機能しません App Intentを使用すると ウィジェットでボタンやトグルなどの 操作ビューを作成できますが このウィジェット体験も カスタムアクションを 追加することで改善できます 私は新しいウィジェットをアプリに 追加して 行きたい海の評価と 投稿をすぐに実行できるようにしました タップするだけで お気に入りの 海の評価の更新もできます 各ボタンはSwiftUIで ラベル付けされており VoiceOverで起動できます
これは海のビューです 投稿と評価のための 操作ボタンが3つあります カスタムアクションでこのウィジェットの 重要機能の使用感を さらに改善しましょう
アクセシビリティアクション修飾子で App Intentが許可されています これが起動するとウィジェットの インテントと更新が実行されます
カスタムアクションを追加して 海をお気に入りに登録しました magicTapアクションにより ダブルタップで写真も撮れます
これらの変更により お気に入りの海がマーキングされ リストのトップに移動します 「ファンストンビーチ 評価なし ボタン」 「ベイカービーチ 評価なし ボタン」 「お気に入り」
「ベイカービーチ お気に入り ボタン」 今回はアプリのアクセシビリティの 実現方法を解説しました アプリを作成する際は VoiceOverなどの技術をお忘れなく アプリ体験が一層向上するような アクセシビリティAPIの使い所を 探ってみてください そして アクセシビリティの サンプルプロジェクトで アクセシビリティAPIの使い方を確認し SwiftUIの一般的なパターンを 調整できるようにしましょう チーム一同 皆さんのアプリの 素晴らしいアクセシビリティを 楽しみにしています ありがとうございました
-
-
7:27 - Accessibility Label Modifier & Opacity
struct UnreadIndicatorView: View { var isUnread: Bool var body: some View { Circle() .foregroundStyle(.blue) .accessibilityLabel("Unread") .opacity(isUnread ? 1 : 0) } }
-
8:02 - Accessibility Element Children Combine Modifier
var body: some View { HStack { UnreadIndicatorView(isUnread: message.isUnread) MessageContentsView(message: message) Spacer() Button(action: favorite) { favoriteLabel } Button(action: reply) { replyLabel } } .accessibilityElement(children: .combine) }
-
10:37 - Accessibility Conditional Modifiers
var body: some View { Button(action: favorite) { Image(systemName: isSuperFavorite ? "sparkles" : "star.fill") } .accessibilityLabel("Super Favorite", isEnabled: isSuperFavorite) }
-
13:38 - Accessibility Actions Modifier
var body: some View { TripView(trip: trip) .onHover { showAttachments = $0 } .overlay { MessageAttachments(attachments: trip.attachments) .opacity(showAttachments ? 1 : 0) } .accessibilityActions { MessageAttachments(attachments: trip.attachments) } }
-
15:16 - Accessibility Label Modifier
var body: some View { TripView(trip: trip) .accessibilityLabel { label in if let rating = trip.rating { Text(rating) } label } }
-
17:42 - Accessibility Drop Point Modifier
var body: some View { CommentAlertView(contact: contact) .onDrop(of: [.audio], delegate: delegate) .accessibilityDropPoint(.leading, description: "Set Sound 1") .accessibilityDropPoint(.center, description: "Set Sound 2") .accessibilityDropPoint(.trailing, description: "Set Sound 3") }
-
19:45 - Accessibility App Intent Action Modifier
var body: some View { ForEach(beaches) { beach in BeachView(beach) .accessibilityAction( named: "Favorite", intent: ToggleRatingIntent(beach: beach, rating: .fullStar)) .accessibilityAction( .magicTap, intent: ComposeIntent(type: .photo)) } }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。