ハイライト
iOS 15で導入
UIButtonConfiguration、プロパティごとの設定の代わりに宣言型構成を使用し、トグル ボタン、ポップアップ ボタン、およびUIMenuラジオ選択サブメニューを使用すると、ボタンを「クリックできる」状態から「表現できる」状態に進化させることができます。
主な内容
ボタンはすべてのアプリで最も一般的なコントロールですが、UIKit のボタン API は何年も原始的なものでした。タイトル、アイコン、背景色、角丸、間隔を設定する必要があります。各属性は個別に調整する必要があります。状態が変化するとスタイルを手動で更新する必要があり、コードがあちこちに散在します。
iOS15の場合UIButtonConfigurationボタンシステムは完全に再構築されました。中心的なアイデアは、ボタンのすべての視覚属性を値タイプ構成にパッケージ化し、構成を変更することでボタンの外観を変更することです。このシステムは 4 つのプリセット スタイル (プレーン、グレー、色付き、塗りつぶし) を提供し、タイトル + サブタイトル + アイコンの組み合わせ、ダイナミック タイプ、複数行テキストをサポートし、読み込みインジケーターを表示することもできます。
より実用的なのは、トグル ボタン (スイッチのように選択状態を切り替える) とポップアップ ボタン (クリックしてメニューをポップアップし、現在選択されている項目を表示する) という 2 つの新しいボタン動作の追加です。どちらの動作も以下に基づいていますUIActionそしてUIMenu追加のプロキシ メソッドを記述する必要はありません。
構成を使用してボタンを作成する
(02:13)
始める最も簡単な方法は、既存のボタンに構成を割り当てることです。
let signInButton = UIButton(type: .system)
signInButton.configuration = .filled()
signInButton.setTitle("Sign In", for: [])
キーポイント:
UIButton次のような古い API は自動的に置き換えられます。setTitle) 設定したタイトルとアイコンは構成に組み込まれます- これは、すべてのボタン コードを一度に書き換える必要がなく、段階的に移行できることを意味します。
カスタム構成
(03:20)
構造メソッドを使用してボタンを構成し、すべてのプロパティを一度に設定します。
var config = UIButton.Configuration.tinted()
config.title = "Add to Cart"
config.image = UIImage(systemName: "cart.badge.plus")
config.imagePlacement = .trailing
addToCartButton = UIButton(configuration: config, primaryAction: ...)
キーポイント:
imagePlacementテキストのどちら側にアイコンを配置するかを制御します (.leadingまたは.trailing)- システムはアイコンとテキスト間の間隔を自動的に処理します。
状態主導型の動的更新
(04:45)
ボタンを押すと、アイコンがワイヤーフレームからソリッドに変わります。このエフェクトが使われていますconfigurationUpdateHandler成し遂げる:
addToCartButton.configurationUpdateHandler = { [unowned self] button in
var config = button.configuration
config?.image = button.isHighlighted
? UIImage(systemName: "cart.fill.badge.plus")
: UIImage(systemName: "cart.badge.plus")
config?.subtitle = self.itemQuantityDescription
button.configuration = config
}
キーポイント:
configurationUpdateHandlerボタンの状態が変化すると自動的に呼び出されます- 現在の設定は最初にクロージャで読み取られ、変更後に再び割り当てられます。
isHighlighted、isSelected、isEnabledステータスが変化すると発動します。
外部データが変更されたときに更新を手動でトリガーします。
private var itemQuantityDescription: String? {
didSet {
addToCartButton.setNeedsUpdateConfiguration()
}
}
キーポイント:
setNeedsUpdateConfiguration()フラグボタンを更新する必要があります- システムは次の実行ループでそれを呼び出します。
configurationUpdateHandler
完全にカスタマイズ可能なスタイル
(08:26)
使用UIBackgroundConfiguration背景を細かく制御:
var config = UIButton.Configuration.filled()
config.buttonSize = .large
config.image = UIImage(systemName: "cart.fill")
config.title = "Checkout"
config.background.backgroundColor = .buttonEmporium
let checkoutButton = UIButton(configuration: config, primaryAction: ...)
checkoutButton.configurationUpdateHandler = { [unowned self] button in
var config = button.configuration
config?.showsActivityIndicator = self.isCartBusy
button.configuration = config
}
キーポイント:
buttonSize持っている.small、.medium、.large3つのプリセットshowsActivityIndicatortrue の場合、読み込みアニメーションを表示し、必要に応じてアイコンを置き換えますbackground.backgroundColorカスタムの背景色を設定しても、システムは押された状態および無効な状態の暗くなる効果を自動的に処理します。
Toggle Button
(11:56)
トグルボタンはクリックするたびに自動的に切り替わりますisSelectedステータス、次のように動作しますUISwitchしかし、よりコンパクト:
let stockToggleAction = UIAction(title: "In Stock Only") { _ in
toggleStock()
}
let button = UIButton(primaryAction: stockToggleAction)
button.changesSelectionAsPrimaryAction = true
button.isSelected = showingOnlyInStock()
キーポイント:
changesSelectionAsPrimaryAction = trueトグル動作を有効にする- クリックするとシステムが自動的に反転します
isSelected - で見つけることができます
configurationUpdateHandler中程度の基準isSelected見た目を変える UIBarButtonItemこちらも追加isSelected属性、同じトグル動作をサポート
Pop-up Button
(14:30)
ポップアップ ボタンは、ポップアップ メニューをクリックします。項目を選択すると、ボタンのタイトルが選択した項目に自動的に更新されます。
let colorClosure = { (action: UIAction) in
updateColor(action.title)
}
let button = UIButton(primaryAction: nil)
button.menu = UIMenu(children: [
UIAction(title: "Bondi Blue", handler: colorClosure),
UIAction(title: "Flower Power", state: .on, handler: colorClosure)
])
button.showsMenuAsPrimaryAction = true
button.changesSelectionAsPrimaryAction = true
// 读取当前选中项
updateColor(button.menu?.selectedElements.first?.title)
// 程序化设置选中项
(button.menu?.children[selectedColorIndex()] as? UIAction)?.state = .on
キーポイント:
showsMenuAsPrimaryAction = trueポップアップメニューを直接クリックしてみましょうchangesSelectionAsPrimaryAction = trueボタンにポップアップ動作を持たせる- ボタンのタイトルとアイコンには、現在選択されている項目が自動的に表示されます
selectedElements常に 1 つの要素を返します (無線制約)
ラジオサブメニュー
(18:18)
並べ替えオプションなど、プルダウン メニュー内にラジオのサブメニューを入れ子にします。
let sortMenu = UIMenu(title: "Sort By", options: .singleSelection, children: [
UIAction(title: "Title", handler: sortClosure),
UIAction(title: "Date", handler: sortClosure),
UIAction(title: "Size", handler: sortClosure)
])
let topMenu = UIMenu(children: [
UIAction(title: "Refresh", handler: refreshClosure),
UIAction(title: "Account", handler: accountClosure),
sortMenu
])
let sortSelectionButton = UIBarButtonItem(primaryAction: nil, menu: topMenu)
キーポイント:
options: .singleSelectionサブメニューをラジオモードにします- 選択された動作は自動的に管理されるため、状態を手動で維持する必要はありません
- 同じ無線制約がネストされたサブメニューに適用されます
##詳細
4 つのプリセット スタイル
iOS 15 では、次の 4 つの基本的なボタン スタイルが提供されます。
| スタイル | 外観 | 該当するシナリオ |
|---|---|---|
| プレーン | 背景なし、テキスト + アイコン | ツールバー、ナビゲーションバー |
| グレー | 灰色の角の丸い背景 | 写真 灰色の丸い角の背景二次的な操作 |
| 色付き | テーマカラーの透明な背景 | 写真強調するが目立ちすぎない |
| 満たされた | 塗りつぶされたテーマの色 | 主な業務 |
レイアウト制御
UIButton.Configuration細かいレイアウト制御を提供します。
var config = UIButton.Configuration.filled()
config.contentInsets = NSDirectionalEdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16)
config.imagePadding = 8
config.titlePadding = 4
config.titleAlignment = .leading
config.imagePlacement = .top
キーポイント:
contentInsetsボタンのコンテンツ領域と境界線の間の間隔を制御しますimagePaddingアイコンとテキスト間の間隔を制御するtitlePadding複数行のタイトル間の間隔を制御するimagePlacementサポート.leading、.trailing、.top、.bottom
Mac Catalyst の自動適応
(15:43)
新しいボタン タイプは、Mac Catalyst でネイティブの Mac スタイルに自動的に変換されます。
- プルダウン ボタンは Mac のベゼル付きプルダウン ボタンになります
- ポップアップボタンがMacのポップアップボタンになります
- トグルボタンが Mac のトグルボタンになります
iPad のスタイル (目立つカスタム ボタンなど) を維持したい場合は、次のように設定できます。
checkoutButton.behaviorStyle = .ipad
重要ポイント
- すべてのカスタム ボタンのサブクラスを置き換えます
- やるべきこと: プロジェクトを継承します
UIButtonカスタム ボタン クラスを作成し、段階的に移行します。UIButtonConfiguration - *なぜやる価値があるのか: 「アイコンが付いた丸いボタン」や「押すと色が変わるボタン」を作るために、多くの人が書いています
CustomButton: UIButton。現在、システムはそれをネイティブにサポートしており、コードは数十行からわずか数行に削減されました。 - 開始方法: 最も単純なカスタム ボタンを見つけて使用します。
.filled()または.tinted()構成の置き換え、見た目の一貫性を確認した上で一括移行
- UISwitch をトグル ボタンに置き換えます
- 対処方法: 設定ページ、フィルター条件などで、
UISwitchテキストラベル付きのトグルボタンに変更 - 実行する価値がある理由:
UISwitchスイッチの状態のみ文字による説明がないため、何が切り替わっているのか分かりません。トグル ボタンはラベルとコントロールを 1 つに結合し、スペースを節約し、セマンティクスをより明確にします。 - 開始方法:
changesSelectionAsPrimaryAction = true+でconfigurationUpdateHandlerに基づくisSelectedアイコンと色の切り替え
- セグメント化されたコントロールをポップアップ ボタンに置き換えます
- 対処法: オプションが 3 ~ 4 つ以上ある場合は、代わりにポップアップ ボタンを使用してください。
UISegmentedControl - 実行する価値がある理由: オプションが多い場合、セグメント化されたコントロールではテキストが切れたり、画面からはみ出したりすることがあります。ポップアップボタンは幅の制限がなく階層構造も表示可能
- 開始方法: 作成する
UIMenu+showsMenuAsPrimaryAction = true+changesSelectionAsPrimaryAction = true
- 読み込みステータスを含む送信ボタンを作成します
- 内容: フォーム送信ボタンはリクエスト中に読み込みアニメーションを表示し、リクエストが完了すると再開します。
- 実行する価値がある理由:
showsActivityIndicator1 行のコードで実装されたシステムは、手動で管理することなく、アイコンの置換とアニメーションを自動的に処理します。UIActivityIndicatorView - 開始方法:
configurationUpdateHandlerリクエスト状況に応じて設定config?.showsActivityIndicator = isLoading
- アプリ内のすべてのボタンのスタイルを統一します
- やるべきこと: 一連のアプリレベルのボタン構成ファクトリ メソッドを定義すると、すべてのボタンがファクトリを通じて作成されます。
- 実行する価値がある理由:
UIButtonConfigurationバリュー型なので再利用・組み合わせが可能です。意味primaryButtonConfig()、secondaryButtonConfig()アプリ全体で一貫したボタン スタイルを確保するには、ファクトリ メソッドを待ちます - 開始方法: 1 つ書いてください
ButtonStyle列挙。それぞれのケースで事前構成された値が返されます。UIButton.Configuration
関連セッション
- UIKit の新機能 — UIKit の年次新機能の概要
- スタイルを使用してインターフェイスを構築 — Interface Builder の新しいボタン システムの使用
- Mac Catalyst の新機能 — ボタンの自動適応などの Mac Catalyst の新機能
コメント
GitHub Issues · utterances