WWDC Quick Look 💓 By SwiftGGTeam
Meet the UIKit button system

Meet the UIKit button system

元の動画を見る

ハイライト

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ボタンの状態が変化すると自動的に呼び出されます
  • 現在の設定は最初にクロージャで読み取られ、変更後に再び割り当てられます。
  • isHighlightedisSelectedisEnabledステータスが変化すると発動します。

外部データが変更されたときに更新を手動でトリガーします。

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

重要ポイント

  1. すべてのカスタム ボタンのサブクラスを置き換えます
  • やるべきこと: プロジェクトを継承しますUIButtonカスタム ボタン クラスを作成し、段階的に移行します。UIButtonConfiguration
  • *なぜやる価値があるのか​​: 「アイコンが付いた丸いボタン」や「押すと色が変わるボタン」を作るために、多くの人が書いていますCustomButton: UIButton。現在、システムはそれをネイティブにサポートしており、コードは数十行からわずか数行に削減されました。
  • 開始方法: 最も単純なカスタム ボタンを見つけて使用します。.filled()または.tinted()構成の置き換え、見た目の一貫性を確認した上で一括移行
  1. UISwitch をトグル ボタンに置​​き換えます
  • 対処方法: 設定ページ、フィルター条件などで、UISwitchテキストラベル付きのトグルボタンに変更
  • 実行する価値がある理由:UISwitchスイッチの状態のみ文字による説明がないため、何が切り替わっているのか分かりません。トグル ボタンはラベルとコントロールを 1 つに結合し、スペースを節約し、セマンティクスをより明確にします。
  • 開始方法:changesSelectionAsPrimaryAction = true+でconfigurationUpdateHandlerに基づくisSelectedアイコンと色の切り替え
  1. セグメント化されたコントロールをポップアップ ボタンに置​​き換えます
  • 対処法: オプションが 3 ~ 4 つ以上ある場合は、代わりにポップアップ ボタンを使用してください。UISegmentedControl
  • 実行する価値がある理由: オプションが多い場合、セグメント化されたコントロールではテキストが切れたり、画面からはみ出したりすることがあります。ポップアップボタンは幅の制限がなく階層構造も表示可能
  • 開始方法: 作成するUIMenu + showsMenuAsPrimaryAction = true + changesSelectionAsPrimaryAction = true
  1. 読み込みステータスを含む送信ボタンを作成します
  • 内容: フォーム送信ボタンはリクエスト中に読み込みアニメーションを表示し、リクエストが完了すると再開します。
  • 実行する価値がある理由:showsActivityIndicator1 行のコードで実装されたシステムは、手動で管理することなく、アイコンの置換とアニメーションを自動的に処理します。UIActivityIndicatorView
  • 開始方法:configurationUpdateHandlerリクエスト状況に応じて設定config?.showsActivityIndicator = isLoading
  1. アプリ内のすべてのボタンのスタイルを統一します
  • やるべきこと: 一連のアプリレベルのボタン構成ファクトリ メソッドを定義すると、すべてのボタンがファクトリを通じて作成されます。
  • 実行する価値がある理由:UIButtonConfigurationバリュー型なので再利用・組み合わせが可能です。意味primaryButtonConfig()secondaryButtonConfig()アプリ全体で一貫したボタン スタイルを確保するには、ファクトリ メソッドを待ちます
  • 開始方法: 1 つ書いてくださいButtonStyle列挙。それぞれのケースで事前構成された値が返されます。UIButton.Configuration

関連セッション

コメント

GitHub Issues · utterances