Build with iOS pickers, menus and actionsをみた #WWDC20
こちらの記事には非公開の情報が含まれているのでApple Developer Programに登録しNDAに合意している方のみ閲覧してください
今朝はDesignの方をみたので実装方法についてみていきます。
細かなアップデートから
UISliderとUIProgressViewはプラットフォームで一貫性を持たせるためにマイナーアップデートされた。トラックの厚みが増してmacOSらしくなった。UISliderはmacOSの動作を採用して、トラックをタップ、クリックで値を調整できるように。
Mac Catalystでの詳細についてはOptimize the Interface of your Mac Catalyst Appを参照。
UIActivityIndicatorView
ペダルの数が少なくなり、サイズに一貫性があり、アニメーションのタイミングも調整されている。Pull to refreshについても同様の更新が反映されている。
Catalystアプリで多くのコンポーネントがMacに最適化された。
UIPickerViewについてもスタイルが更新されている。
UIPageControlにもアップデートが入っている。無制限のページ数をサポート、スクロールやスクラブが可能に。ページに特別な意味がある場合には、ページごとにカスタムイメージを設定することも可能。
現在地のアイコンを変更しているページコントロールの例
UIPage Controlのコードの例
let pageControl = UIPageControl()
pageControl.numberOfPages = 5
pageControl.backgroundStyle = .prominent
pageControl.preferredIndicatorImage =
UIImage(systemName: "bookmark.fill")
pageControl.setIndicatorImage(
UIImage(systemName: "heart.fill"), forPage: 0)
Color Picker
既にmacOSのカラーパネルに慣れている人には親しみやすい。シートとして表示したりポップオーバーとして表示したりできる。
画面から色を選択している様子
Catalystでの表示の様子
カラーピッカーをコードで利用する方法
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
}
Date Picker
新しいものではないが、汎用性とUXを大きく改善した。iOS 14/iPadOS 14ではコンパクトなスタイルが利用可能に。日付・時刻を選択してモーダルで選択画面を呼び出すことができる。macOSと同様の操作感を実現。
日付だけや時刻だけを選択するように制限することも可能。インラインスタイルで画面に埋め込むことも。
コンパクトなDate Pickerを表示するコードの例
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)
値が変更されたことを受け取るのは簡単。
Menu
Safariはタブボタンをタップと長押しで動作が変わる。長押しするとメニューが表示される。実装方法としては
button.menu = UIMenu(...)
barButtonItem.menu = UIMenu(...)
を設定する。リマインダーアプリでは長押しせずにそのままメニューが表示される。これはshowsMenuAsPrimaryAction = trueを設定することで実装できる。しかし、barButtonItemにはこれはサポートされない。
戻るボタンに自動的にメニューが表示されるようになった。
タイトルは
.backBarButonItem.title
.backButonTitle
.title
から選択される。適切なタイトルになるようにコントロールする必要がある。
UIControlはUIContextMenuInteractionへのアクセスとそのインタラクションを有効にするためのプロパティを提供する。
カスタムメニューのベースのUIをサポートするためにUIControlをサブクラス化し、UIContextMenuInteractionDelegateの実装を上書きすることができる。メインジェスチャーが認識されたときにアクションを起こすには、menuActionTriggeredコントロールイベントに登録することができる。
UIDeferredMenuElement
メニュー項目を非同期に提供する機能を追加。UIKit は最終的なメニュー項目が提供されるのを待っている間、標準の読み込みUIを表示する。
UIDeferredMenuElementは複雑なメニューを生成するのにも便利。
UIContextMenuInteraction
2つの新機能について。
updateVisibleMenu(_ block: (UIMenu) -> UIMenu)
メニューのコピーを受け取りその場所に表示するメニューを返す。UIMenuは子プロセスが不変であることを強制しないように挙動を変更した。新しいメニューを作成する代わりにブロックに渡されたメニューを更新して返すことができる。
インタラクションの表示に関するプロパティが追加になった。これ以外にも.noneを設定することができる。
UIAction
UIBarButtonItem のイニシャライザが追加された。
init(systemItem:primaryAction:menu:)
init(title:image:primaryAction:menu:)
また、ほとんどすべてのパラメータはオプションなので、必要なものだけを指定すればいい。コードを見てみる。
self.toolbarItems = [
UIBarButtonItem(systemItem: .save, primaryAction: saveAction, menu: saveMenu),
.fixedSpace(width: 20.0),
UIBarButtonItem(image: optionsImage, menu: optionsMenu),
.flexibleSpace(),
UIBarButtonItem(primaryAction: revertAction),
]
UIButtonの変更
UIActionと一緒にボタンの種類を受け入れるイニシャライザを追加した。
UISegmentedControlの変更
これまではセグメントが選択されたごとに色や変えようと思うと下記のように大変だった
let control = UISegmentedControl(frame: frame, actions: Colors.allCases.map {
UIAction(title: color.description) { [unowned imageView] _ in
imageView.tintColor = color.color()
}
})
上記のように簡単に書けるようになり、色を増やす場合はenumのcaseを増やせば良い。
初期化に始まり、追加、削除、更新のためのメソッドが追加された。
まとめ
iOS 14/iPadOS 14ではUIも大幅にアップデートされていますね。Date Pickerなどはこれまでも利用していたことも多かったのでiOS 13以下とどう整合性を取りながら利用していけるか色々試して見たいと思います。UIActionによってUIButtonやUIBarButtonItemが便利になりそうで、これによって削除できるライブラリもありそうですね。