ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
iOSピッカー、メニュー、アクションを使った構築
流れるようなインターフェースとアクセスが容易なコンテキストと連動した情報を持つiPhoneやiPadのAppを作成しましょう。最新のUIKitコントロールをAppに組み込むことで、メニュー、日付のピッカー、ページコントロール、セグメントコントローラーを最大限に活用する方法をお見せします。メニューをユーザーインターフェース全体に取り入れ、UIActionがイベントハンドリングを統一する助けとなることを学びましょう。これら新しいコントロールについて学んだ後、"Design with iOS pickers, menus and actions"でこれらのツールとAPIを使って優れたインターフェースをデザインする方法についてもご確認ください。
リソース
関連ビデオ
WWDC20
-
ダウンロード
こんにちは WWDCへようこそ “iOSのピッカー メニュー アクションを使用して構築” ようこそ 私はエリック・デュディアック UIKitチームのエンジニアです 後ほど デヴィッド・ダンカンが 参加します ここでは 標準のコントロールと メニューに焦点を当てて UIKitの すばらしい新機能について 説明します それでは はじめましょう このセッションで説明する内容を 簡単に述べます コントロールの外観に関する 新しい変更点について説明します その後で 新しいカラーピッカーと その使用方法について説明します 次に アップデートされた 日付ピッカーを取り上げます また メニューの変更点や 追加されたオプションについて説明します 最後に コードを劇的に簡素化できる UIActionの改善点について説明します まず いくつかの一般的なコントロールの 外観のアップデートについて説明します これらは UIKitおよびSwiftUIの 両方の該当箇所について iOSとiPadOS全体に適用されます
UISliderおよびUIProgressViewは 両方ともに 小規模なアップデートが行われており すべてのプラットフォームにおける 一貫性を高めています
最初に気づくのが トラックの太さが増したことで― 一層macOSに沿った外観になっています 外観の変更だけでなく 今回 UISliderは macOSの動作を採用し トラックをタップしたり クリックしたりして 値を調整することができます
UIProgressViewについても 同様に 見た目の変更が行われています
これらとその他のUIKitコントロールを 最適化された Catalystアプリケーションで使用すると 一層 macOSらしい外観が 採用されるようになります このさらなる採用によって これらのコントロールの いくつかのカスタマイズAPIが制限され それらのエフェクトがなくなります 最適化された Catalystアプリケーション作成時の 考慮事項について詳しくは “Optimize the Interface of your Mac Catalyst App”セッションをご確認ください
外観のアップデートが行われた コントロールとして 次に取り上げるのは UIActivityIndicatorViewです 新しいデザインの特徴として 処理中にインジケータが少なくなり すべてのサイズで一貫性が保たれています また アニメーションの タイミング調整が行われています 処理中の進捗を示す際には 常に 標準の― UIActivityIndicatorViewを 使用することが重要です これにより 一貫性が確保されます 今回 すべての想定されるシナリオで うまく動作するように ダークモード用に調整された モダンスタイルを使用します オプションとして APIを使用して カスタムカラーを設定することができます
同様の外観の変更が pull-to-refresh コントロールでも行われています
最適化されたMac Catalystバージョンの これらのコントロールと― その他いくつかの標準コントロールです 標準のMacのコントロールの外観と 合致していることに注目してください
UIPickerViewも 外観が アップデートされています ただし 多くのコンテキストで メニューが代わりの役割を果たす場合が あることに注意してください これについては 後ほど説明します macOSのCatalystアプリケーションでは 多くの場合 多数の選択肢から 1つの選択を提示する際に 最適なのはメニューです
考察する最後のコントロールは UIPageControlです 今回 外観の変更とともに 機能的な変更も行われました 新しい外観では 固定されたサイズ内で ページコントロールが 無制限のページ数を サポートできるようになりました
ページ数がスペースの許容範囲を超えても このコントロールによって ページの スクラブとスクロールが可能になるため さまざまなシナリオに コントロールが 適応できるようになっています 例えば ホーム画面上など ユーザーのカスタマイズによって ページ数が大きく増えた場合などに役立ちます また このページコントロールは 外観をカスタマイズするための 新しいAPIを備えています
インジケータ自体を 個々のページ単位でも すべてのページ単位でも カスタムイメージに 設定できるようになりました これは 特定のページが 特殊な機能を持つ場合に役立ちます 例えば ここに示した 天気アプリケーションの最初のページは 天気を示す現在地のアイコンが表示されます
コントロールの見栄えや 動きもカスタマイズできます 例えば インターフェースの メインコントロールである場合に より目立つモードで コントロールを 表示するように設定できます それでは これらのカスタマイズを どのようにして使用するか見ていきましょう ここでは まずpageControlを作成します
backgroundStyleをprominentに設定できます その結果 アプリケーションのコンテキストで より目立つようになります 操作している時だけでなく 常に背景領域が表示されるようになります
また 通常の円が気に入らない場合に すべてのインジケータに デフォルトの イメージを設定することもできます この場合 ブックマークのページを 参照している際の ブックマークのイメージを設定しています
個々のページを カスタマイズすることもできます ここでは お気に入りであることを示すため 最初のページに― ハートのイメージが 表示されるようにしています pageControlの その他の APIの外観については 一切変更されていません
次に iOS 14の新しいカラーピッカーについて 見てみましょう
macOSのカラーパネルで おなじみのこれらについて iPadOSとiOS 14の新しいカラーピッカーは 非常に似ていると感じることでしょう カラーピッカーは アプリケーションから シートまたはポップオーバーとして 簡単に提示できる ビューコントローラーです よく使用される デリゲートコールバックに加えて 設定して読み込んで構成できる カラープロパティを備えています 提示されると さまざまな方法で色を選択できます 例えば グリッドから選んだり
スペクトル勾配全体から 色を選択したり 赤 緑 青のコンポーネントで 正確な色を手動で指定したりできます 16進数のコードで指定することも可能です よく使用する色は お気に入りにして アプリケーション全体で再利用できます そのため プロアプリケーションでは 1つのコンテキストでブランドカラーなどの 重要なものを簡単に選択して 多くのコンテキストでそれを使用できます 最後に macOSパネルと同じように カラーピッカーでは eyedropperツールを使用して 画面のあらゆる場所から 色をつかむことができます
これは 複数のアプリケーション実行中の iPadOSで特に強力です 色を画面のあらゆる場所から 簡単に選択し マッチングして 再使用することができます
macOSで ピッカーは 標準のカラーピッカーパネルを使用しており 使い慣れた同じ機能を実現しています
それでは カラーピッカーの設定と 使用について見てみましょう この場合 ColorPickerViewController プロパティが 既存のviewControllerにあります カラーボタンを押すと viewController上の色を使用する 現在の色に設定し ColorPickerViewControllerを提示します
ユーザーの色の選択が終了すると 次に アプリケーションにその色を設定します ユーザーが色の選択をキャンセルすると その色は無事に無視されます 色の選択方法や eyedropperツールの サポートについて まったく気にする必要はありません すべて カラーピッカーによって 自動的に処理されます
iOSとiPadOSの日付ピッカーは 新しいコントロールではありませんが その多用途性と ユーザーエクスペリエンスについて 大幅な改善を行っています
iPadOSとiOS 14で 新しくなった点として コンパクトスタイルが使用可能になり サポートされています 前に導入済みのmacOSバージョンと同様に iOSのコンパクトスタイルでは フィールドで時間と日付が表示され タップするとことで モーダル選択が表示されます
これは テーブルビューや 複数のフィールドを持つフォームなど UIでスペースが限られている場合に 特に有効です 日付側から選択すると モーダルカレンダーが表示され 任意の日付を簡単に選択できます
また 従来のホイール型よりも 遠く離れた日付をより迅速に選択でき iPadにおけるポインター操作用に 最適化されています 時間をタップすると キーパッドを使用して時間を選択できます
既に述べたように コンパクトスタイルは macOS Catalinaでサポートされており iOS 13.4 SDK以降でも サポートされています これによって 最適化された― または 最適化されていない Catalystアプリケーションに Mac上の日付ピッカーの表示を より適切に サポートさせることが可能になります 使用する際は 日付ピッカーコントロールは UILabelと同じようにサイズ調整されます 日付のコンポーネントをクリックすると モーダルカレンダーが提示されて 日付を選択できます 日付と時間は フィールドに 値を入力することでも設定できます また 指定されたコンテキストで時間のみ または日付のみが必要な場合 フィールドのその部分のみに ピッカーを制限することができます また iOS 14は 日付ピッカーに インラインスタイルを導入しています これは 日付の選択が UIの主要機能であり― モーダルステップの追加が 単純に不要な場合に 特に有効です また より多くの画面スペースが使用可能な iPadアプリケーションが ホイールスタイルから 移行する場合にも有効です 見栄え自体は コンパクトスタイルから 提示されるモーダル版と合致しており コントロールから提示されるというよりも コントロールの内容を埋める感じになります 3つすべての新しいスタイルについて 優れた部分は UIDatePickerのAPIが まったく同じであることです そのため 新しいスタイルは コンテキストに応じて 容易に採用し 調整でき アプリケーションのレイアウトが 影響を受けるだけです それでは これらの新しいスタイルの 使用について見てみましょう 日付ピッカーの作成と初期日付の設定は iOS 14でまったく変わりません また 選択肢に最小日付と最大日付を 設定できます 新しいスタイルを使用するために必要なのは お気に入りのスタイルを設定することだけです ここでは コンパクトスタイルに設定します
また 必要に応じて 日付ピッカーの ロケールとカレンダーをカスタマイズできます これで 新しいスタイルは 適切な内容を表示します この場合 日本のカレンダーが表示されます 年が過去の場合に どのように 年代を表示するか分かります
また このコンテキストで 時間が適切でない場合に 選択を日付のみに制限することもできます
日付ピッカーは UIControlの1つで あることに変わりはありません そのため 値が変化したり 新しい日付を読み込んだりした時に 簡単に通知できます 新しい日付ピッカーのスタイルは アプリケーションで 日付を選択する際の エクスペリエンスを向上します プラットフォーム全体で さまざまな 異なるカレンダーや操作に伴う 複雑さの多くを アプリケーションが 処理する必要がないためです
ここで 同僚のデヴィッドに交代します ありがとう エリック デヴィッド・ダンカンです メニューとUIActionに関する 改善点について説明します 最初に iOS 14で UIのより多くの部分に対して 迅速かつ軽量なメニュー操作が 実現されている点について説明します iOS 14のあらゆるアプリケーションは UIButtonsとUIBarButtonItemsに 簡単にメニューを追加できます
これは Safariがメニューを使用して 簡単に機能を強化できる例です この操作について見てみましょう
タブスイッチボタンをタップすると デフォルトのアクションが実行され Safariタブスイッチャーが表示されます
iOS 14では― このボタンを長押しすると より多くの オプションを備えたメニューが提示されます すぐに指をスライドさせて 項目を選択し 引き上げるとアクティブにできます
このようなメニューをアプリケーションに 追加する方法を見てみましょう
UIButtonとUIBarButtonItemは メニューを直接サポートしており メニューの追加はこの上なく簡単です いずれかのクラスのmenuプロパティに メニューを割り当てるだけです UIKitで 長押しすると そのメニューが 表示されるようにします 場合によっては 即座に 表示したいこともあるでしょう その操作について見てみましょう “リマインダー” リマインダーは Moreボタンを使用して 複数のアクションをグループ化します Safariの例と異なり メニューは ボタンに触れると即時に提示されます 前と同じように ユーザーは 指をスライドさせて 軽やかなジェスチャー1つで アクションを即座に選択できます この操作の選択方法は UIButtonと UIBarButtonItemで異なります UIButtonの場合 showsMenuAsPrimaryActionを trueに設定することで タッチダウンすると 即座に メニューを提示させるようにできます
UIBarButtonItemの場合 メニューを指定し プライマリアクションを設定しないことで タッチダウンしたら 即座にメニューが表示されます
iOS 14では ナビゲーションバーの Backボタンで メニューが自動的に提示されます
このメニューは あらゆるアプリケーションで ナビゲーションスタックに― ジャンプバックするための 標準のアクセレレーターを作成します
メニューのタイトルは 必要に応じて カスタマイズされたBackボタンを考慮して 自動的に選択されます カスタムタイトルビューを使用し ナビゲーション項目のタイトルを 設定しない場合は backButtonTitleを設定して 良好な エクスペリエンスの確保を検討してください
これまで見てきた新しいメニューサポートは UIControlによって提供されています 長押しまたはタッチダウンで メニューが トリガーされるかどうかを決定する― showsMenuAsPrimaryActionについては 既に見てきました
UIControlは contextMenuInteractionへの アクセスを提供し その操作を有効化するプロパティを提供します カスタムのメニューベースのUIをサポート するために UIControlをサブクラス化し― ContextMenuInteractionDelegateの 実装をオーバーライドできます
メニュージェスチャーが認識された時に アクションを起こすために menuActionTriggeredコントロールイベントに 登録できます ここで メニューの強力な新機能を考察し メニューを使用できる 新しいケースについて見てみましょう
UIDeferredMenuElementは 非同期で メニュー項目を提供する機能を追加します 例が示すとおり UIKitは 最終的なメニュー項目が 提供されるのを待っている間 ロード中であることを示す 標準的なUIを提示します
一度メニューが提供されたら メニューが再度表示される場合に メニュー項目はキャッシュに入れられます UIDeferredMenuElementは 複雑なメニューを 生成する場合にも有効で 表示が必要になるまで メニュー項目を要求しません 次に UIContextMenuInteractionの 2つの新機能に注目します
updateVisibleMenuによって ユーザーに 現在提示されている メニューをアップデートできます メニューのコピーを受け取ってから メニューを返して 適切な場所に表示します
このAPIをとても使いやすくするために UIMenuは 子を強制的に不変のものに しないよう動作を変更し 新しいメニューを作成するのではなく ブロックに渡されたメニューを アップデートして返すことが できるようにします UIContextMenuInteractionが 操作の外観用に クエリを提供するようになりました このプロパティは プレビューを 表示する時に“rich”を返し メニューのみの操作や 何もない場合には“compact”を返します コントロールが常に コンパクトの外観を使用する場合は 操作は トリガーされる方法に基づいて richまたはcompactを表示します iOS 14で メニューを より向上させる新機能については以上です 次に UIActionがどのように改善して ユーザー入力に対するアクションが 簡単になったかを説明します iOS 13で UIKitはイベント処理コードの共有を 容易にするために UIActionを導入しました 思い返すには― WWDC 2019の“Modernize your UI for iOS 13”を ご確認ください iOS 14では アプリケーションで UIActionを 使用できる場所と方法が拡張されました
UIBarButtonItemは アクションと メニューを備えた項目を― 作成するための 新しい初期化子を 追加しています これによって タップへの応答 メニューの提示および その両方を行う― BarButtonItemsの作成が 容易になりました ほとんどすべてのパラメーターは オプションで― 必要なパラメーターを指定するだけです それでは見てみましょう
ここでは iOS 14の 新しいAPIを使用して viewControllerのツールバー項目を設定します
まず タップされるとアクションをトリガーとし 長押しするとメニューをトリガーする システム項目を作成します
次に 新しいfixedSpace width APIを使用し fixedSpaceを追加します
イメージを表示し タッチダウンすると メニューを提示するように設定された カスタム項目を追加します
そしてflexibleSpaceです これも新しいAPIを使用しています
最後に primaryActionのタイトル またはイメージを使用し タップすると ハンドラを トリガーする項目があります BarButtonItems同様 すべてのコントロールは UIActionで作成できますが UIButtonとUISegmentedControlの 2つのコントロールは 追加の動作があります
UIButtonは― UIActionの横にあるボタンタイプを受け取る 新しい初期化子を追加します タイプはデフォルトでsystemになり プライマリアクションのタイトルとイメージを 使用して 必要に応じてボタンを設定します primaryActionを使用して作成された 他の コントロール同様 そのアクションは登録され primaryActionTriggeredコントロール イベントを処理し ボタンがタップされると アクションハンドラが呼び出されます
UIActionのセグメント化コントロールの サポートを見る前に iOS 14より前は どのようにして 設定したかを見てみます
まず 文字列の配列で コントロールを作成します 次に メソッドを呼び出すハンドラを追加し コードのどこかに配置します このメソッドは 変化する可能性のある マッピングを想定して 選択されたセグメントを 切り替える必要があります マッピングが変化した場合 コンパイラは問題の検出を サポートできません iOS 14では これがより簡単になっています
UIActionによる セグメント化コントロールの 作成は次のとおりです UIActionの配列でコントロールを作成し それぞれが1つのセグメントの タイトルまたはイメージを定義します 前と異なり イベントハンドラを 追加する必要はありません UIKitは セグメントが選択され そのセグメントのみである場合に アクションのハンドラを自動的に呼び出します
切り替えのステートメントは必要ありません 問題の検出のための デフォルトのケースもありません ハンドラは コントロール作成に 伴って存在します コンパイラは ユーザー入力に対する 設定と応答を― 同期的に維持するための サポートを提供します
ここで 列挙を使用して アクションを生成します これは新しい列挙ケースを 追加できることを意味し セグメント化コントロールの動作は自動的に アップデートされることを意味します これをコントロールイベント処理と 組み合わせて 両方の良さを 引き出すことができます
UIActionのUISegmentedControlの採用は 新しい初期化子から始まり セグメントの追加 除去 アップデート 検索用の新しいメソッドを追加します 既に見てきたとおり UIActionに 関連付けられたセグメントは それが選択された時にのみ呼び出される アクションのハンドラを持っています
iOS 14は iPhone iPad Mac Catalyst用の アプリケーションを強化するために 多くを提供できます ストックコントロールの新しい外観 UIPageControlの新しいカスタマイズ性 UIDatePicker用の新しいスタイルを 活用して UIを刷新します すべての色選択ニーズに対して ColorPickerControllerを採用し ユーザーが表示する色を 簡単に選択できるようにします アプリケーションのメニューの活用を より簡単かつ迅速にして 指をスライドさせるだけで あらゆるタスクを 始められるようにします Backボタンメニューが明確かつ 正確になったことで アプリケーション内の迅速な ナビゲーションをサポートします
UIActionを活用して ユーザー入力を 処理するコードを簡素化し共有します お客様がアプリケーションを強化するのを 楽しみにしています ご視聴 ありがとうございました
-
-
4:34 - UIPageControl example
let pageControl = UIPageControl() pageControl.numberOfPages = 5 pageControl.backgroundStyle = .prominent pageControl.preferredIndicatorImage = UIImage(systemName: "bookmark.fill") pageControl.setIndicatorImage( UIImage(systemName: "heart.fill"), forPage: 0)
-
6:56 - UIColorPickerViewController example
var color = UIColor.blue var colorPicker = UIColorPickerViewController() func pickColor() { colorPicker.supportsAlpha = true colorPicker.selectedColor = color self.present(colorPicker, animated: true, completion: nil) } func colorPickerViewControllerDidSelectColor(_ viewController: UIColorPickerViewController) { color = viewController.selectedColor } func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) { // Do nothing }
-
10:04 - UIDatePicker example
let datePicker = UIDatePicker() datePicker.date = Date(timeIntervalSinceReferenceDate: timeInterval) datePicker.preferredDatePickerStyle = .compact datePicker.calendar = Calendar(identifier: .japanese) datePicker.datePickerMode = .date datePicker.addTarget(self, action: #selector(dateSet), for: .valueChanged)
-
14:20 - UIDeferredMenuElement example
button.menu = UIMenu(title: "", children: [ UIMenu(title: "", options: .displayInline, children: (1...2).map { UIAction(title: "Static Item \($0)") { action in }}), UIDeferredMenuElement({ completion in DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { completion([UIMenu(title: "", options: .displayInline, children: (1...2).map { UIAction(title: "Dynamic Item \($0)") { action in }})]) } }), ])
-
14:50 - updateVisibleMenu example
self.contextMenuInteraction.updateVisibleMenu { currentMenu -> UIMenu in currentMenu.children.forEach { element in guard let action = element as? UIAction else { return } action.state = Bool.random() ? .off : .on action.attributes = Bool.random() ? [.hidden] : [] } return currentMenu }
-
16:05 - UIBarButtonItem example
let saveAction = UIAction(title: "") { action in } let saveMenu = UIMenu(title: "", children: [ UIAction(title: "Copy", image: UIImage(systemName: "doc.on.doc")) { action in }, UIAction(title: "Rename", image: UIImage(systemName: "pencil")) { action in }, UIAction(title: "Duplicate", image: UIImage(systemName: "plus.square.on.square")) { action in }, UIAction(title: "Move", image: UIImage(systemName: "folder")) { action in }, ]) let optionsImage = UIImage(systemName: "ellipsis.circle") let optionsMenu = UIMenu(title: "", children: [ UIAction(title: "Info", image: UIImage(systemName: "info.circle")) { action in }, UIAction(title: "Share", image: UIImage(systemName: "square.and.arrow.up")) { action in }, UIAction(title: "Collaborate", image: UIImage(systemName: "person.crop.circle.badge.plus")) { action in }, ]) let revertAction = UIAction(title: "Revert") { action in } self.toolbarItems = [ UIBarButtonItem(systemItem: .save, primaryAction: saveAction, menu: saveMenu), .fixedSpace(width:20.0), UIBarButtonItem(image: optionsImage, menu: optionsMenu), .flexibleSpace(), UIBarButtonItem(primaryAction: revertAction), ]
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。