Highlight
iOS 26 の新デザインを UIKit レイヤーでどう適合させるかを網羅的に解説。Tab、Navigation Bar、Presentation、Search、Controls、カスタム Glass の 6 領域をカバーします。
核心となる内容
既存アプリを iOS 26 SDK で再コンパイルするだけで、Tab Bar が浮き上がり、Navigation Bar が透過し、ボタンには Liquid Glass の背景が現れます。問題はその先です。「統一された見た目」を作るためにこれまで追加してきた UIBarAppearance、backgroundColor、ボタンの独自カラーリングといったコードは、いまや Glass エフェクトを覆い隠してしまいます。Sanaa(UIKit チームのエンジニア)は、このセッションのほぼ 25 分間を使って、6 つの領域それぞれで再理解が必要なポイントを順に解説しています。
ビデオ全体を貫く主軸はこうです。UIKit は Tab Bar、Split View、Navigation Bar、Toolbar、Presentation、Search Bar、Slider/Switch などのコンポーネントについてマテリアルとレイアウトを作り直しました。開発者がやるべきことは、古いカスタムコードを削除し、自動挙動ではカバーしきれない細部を新しい API で構成することです。たとえば Tab Bar のスクロール時最小化は tabBarMinimizeBehavior 1 行で済み、Sidebar 下のアートワーク延伸は UIBackgroundExtensionView、モーダル遷移のモーフは preferredTransition = .zoom、カスタム Glass は UIGlassEffect と UIVisualEffectView の組み合わせに任せます。どの API も具体的なシーンに対応しており、「柔軟性」のような抽象論はありません。
詳細な内容
Tab Bar とボトム Accessory(02:31 から)
// Minimize tab bar on scroll
tabBarController.tabBarMinimizeBehavior = .onScrollDown
// Add a bottom accessory
let nowPlayingView = NowPlayingView()
let accessory = UITabAccessory(contentView: nowPlayingView)
tabBarController.bottomAccessory = accessory
ポイント:
tabBarMinimizeBehavior = .onScrollDown: 下方向スクロールで Tab Bar を隠し、逆スクロールで復帰させ、フォーカスをコンテンツに譲ります。UITabAccessory: Tab Bar の上に補助ビューをぶら下げる用途で、たとえば音楽アプリの Mini Player に使えます。- Tab Bar が最小化されると
bottomAccessoryはアニメーションしながら Tab Bar 内にインライン表示され、占有スペースが小さくなります。
Accessory ビューの自動適応(03:35):
// Update the accessory with the trait
registerForTraitChanges([UITraitTabAccessoryEnvironment.self]) { (view: MiniPlayerView, _) in
let isInline = view.traitCollection.tabAccessoryEnvironment == .inline
view.updatePlayerAppearance(inline: isInline)
}
// Automatic trait tracking with updateProperties()
override func updateProperties() {
super.updateProperties()
let isInline = traitCollection.tabAccessoryEnvironment == .inline
updatePlayerAppearance(inline: isInline)
}
ポイント:
UITraitTabAccessoryEnvironmentという trait を介して、inline と独立表示の 2 状態を監視します。- inline ではスペースが限られるため、二次的なコントロールは積極的に隠します(音楽アプリでは一部の再生コントロールを非表示にしています)。
updateProperties()は WWDC25 で導入された自動 trait 追跡のエントリーポイントで、詳細は “What’s new in UIKit” を参照してください。
Sidebar 下のアートワーク延伸(05:51)
// Extend content underneath the sidebar
let posterImageView = UIImageView(image: ...)
let extensionView = UIBackgroundExtensionView()
extensionView.contentView = posterImageView
view.addSubview(extensionView)
let detailsView = ShowDetailsView()
view.addSubview(detailsView)
ポイント:
UIBackgroundExtensionViewはコンテンツビュー(ポスターなど)を safe area の外まで埋めます。- デフォルトでは safe area に従って自動延伸し、上部はステータスバーやナビゲーションバーに、リーディングエッジは Sidebar に譲ります。
- 延伸させたくない要素(タイトル、エピソードリスト)は sibling として追加し、
extensionViewの中に入れないようにします。
Navigation Bar のグルーピングとサブタイトル(08:38 / 10:15)
// Custom grouping
navigationItem.rightBarButtonItems = [
doneButton,
flagButton, folderButton, infoButton,
.fixedSpace(0),
shareButton, selectButton
]
// Titles and subtitles
navigationItem.title = "Inbox"
navigationItem.subtitle = "49 Unread"
ポイント:
- システムは規則に従って自動でグルーピングします。アイコンボタンは Glass 背景を共有し、テキストボタン・Done/Close・prominent スタイルは独立した背景を持ちます。
.fixedSpace(0)を挟むと、同種ボタンを強制的に 2 グループに分割できます。例では Share ボタンを切り出しています。navigationItem.subtitleは iOS 26 で追加された API で、タイトルの下にレンダリングされます。largeSubtitleViewは大タイトルの下にインタラクティブなビュー(Mail のフィルタボタンなど)を配置できます。- 大タイトルはコンテンツのスクロールに追随する形に変わったため、scroll view は Navigation Bar の下まで完全に延ばす必要があります。
Edge Effect とカスタムコンテナ(11:20)
// Edge effect's custom container
let interaction = UIScrollEdgeElementContainerInteraction()
interaction.scrollView = contentScrollView
interaction.edge = .bottom
buttonsContainerView.addInteraction(interaction)
ポイント:
- スクロールビューの上下エッジ(Navigation Bar / Toolbar 付近)には自動でビジュアル処理(Scroll Edge Effect)が入ります。
- エッジに浮かべるカスタムコンテナ(フローティングボタン群など)は、
UIScrollEdgeElementContainerInteractionを使って edge effect をコンテナの背後にも適用しないと、コンテナ下の文字がぼやけて読みにくくなります。
Zoom Transition と Action Sheet のアンカー(13:55)
// Morph popover from its source button
viewController.popoverPresentationController?.sourceItem = barButtonItem
// Morph sheet from bar button
viewController.preferredTransition = .zoom { _ in
folderBarButtonItem
}
// Setting source item for action sheets
alertController.popoverPresentationController?.sourceItem = barButtonItem
ポイント:
sourceItemでソースボタンを指定すると、ポップオーバーがそのボタン位置からモーフして展開します。preferredTransition = .zoom { ... }はシート形式の画面に使い、ボタンの形状が新画面に溶け込むように遷移します。- iPhone の Action Sheet も source item にアンカーされるようになり、iPad と同じ挙動になりました。source がない場合は中央表示になり、Cancel ボタンが自動で追加されます。
// Place search bar in a toolbar
toolbarItems = [
navigationItem.searchBarPlacementBarButtonItem,
.flexibleSpace(),
addButton
]
// Place search at the trailing edge of the navigation bar (iPad)
navigationItem.searchBarPlacementAllowsExternalIntegration = true
// Search as a dedicated view
navigationItem.preferredSearchBarPlacement = .integratedCentered
// Tab Bar search shortcut
searchTab.automaticallyActivatesSearch = true
ポイント:
- iPhone では Search Bar を Toolbar に移すのが推奨で、
searchBarPlacementBarButtonItemを使用します。 - iPad で
searchBarPlacementAllowsExternalIntegrationを有効にすると、システムは Navigation Bar のトレーリング側に Search Bar を置きます(macOS 風のレイアウト)。 - Tab Bar の Search Tab は
automaticallyActivatesSearch = trueに設定すると、タップでそのまま入力フィールドに展開されます。
コントロール: Glass Button、Slider、Switch(17:52)
// Standard glass
button.configuration = .glass()
// Prominent glass
tintedButton.configuration = .prominentGlass()
// Neutral slider with 5 ticks and a neutral value
slider.trackConfiguration = .init(allowsTickValuesOnly: true,
neutralValue: 0.2,
numberOfTicks: 5)
// Thumbless slider
slider.sliderStyle = .thumbless
ポイント:
.glass()と.prominentGlass()はUIButton.Configurationに追加された 2 つのファクトリメソッドです。- Slider にはティックモード(
allowsTickValuesOnly)、中性アンカー(neutralValue、写真の明るさ調整での 0 点など)、.thumblessスタイル(つまみなし)が追加されました。 - Switch と Segmented Control の thumb には Liquid Glass のインタラクションアニメーションが付きます。
カスタム Glass: UIGlassEffect とコンテナ(20:28 / 23:52)
// Adopting glass for custom views
let effectView = UIVisualEffectView()
addSubview(effectView)
let glassEffect = UIGlassEffect()
glassEffect.tintColor = .systemBlue
glassEffect.isInteractive = true
UIView.animate {
effectView.effect = glassEffect
}
// Adding glass elements to a container
let container = UIGlassContainerEffect()
let containerView = UIVisualEffectView(effect: container)
let view1 = UIVisualEffectView(effect: UIGlassEffect())
let view2 = UIVisualEffectView(effect: UIGlassEffect())
containerView.contentView.addSubview(view1)
containerView.contentView.addSubview(view2)
ポイント:
UIGlassEffectをUIVisualEffectViewに適用するとき、UIView.animateでラップして代入すると materialize アニメーションが走ります。nilを代入すると dematerialize アニメーションになります。tintColorは Glass を着色し、isInteractive = trueにすると押下時の弾性フィードバックが有効になります。UIGlassContainerEffectは複数の Glass ビューを同じコンテナにまとめ、近づくと自動でマージし、離れると分離します。spacingでマージ距離の閾値を制御します。cornerConfiguration = .containerRelative()を指定すると、子ビューの角丸がコンテナの余白に応じて自動調整されます。
ここから得られる示唆
1. 「自動マイグレーション」を UI 作り直しの第一歩にする
なぜやる価値があるか: iOS 26 SDK で再コンパイルするだけで Liquid Glass エフェクトの大部分が手に入ります。まずは自動の結果を見てから、どこを手で直すかを決めるほうが、ゼロから書き直すより半分以上の作業を省けます。
どう始めるか: 既存アプリを新 SDK でビルドし、画面ごとにスクリーンショットを並べて比較し、「自動でよくなった」「自動で悪くなった」の 2 グループに分けて記録します。前者はそのまま採用し、後者だけ手を入れます。
2. 古い Bar 外観のカスタムコードを削除する
なぜやる価値があるか: UIBarAppearance、backgroundColor、ボタンの独自カラーリングなどの旧コードは Glass マテリアルを直接妨げます。削除しないと新デザインの恩恵は得られません。
どう始めるか: プロジェクト内の UIBarAppearance / setBackgroundImage / barTintColor をすべて検索し、1 つずつ削除可能か評価します。情報伝達上どうしても必要な tintColor と style = .prominent だけを残します。
3. Sidebar のコンテンツを UIBackgroundExtensionView で作り直す
なぜやる価値があるか: iOS 26 で Sidebar が最も映えるのは、その下までコンテンツが延伸している状態(TV App 参照)です。UIBackgroundExtensionView を使えば 1〜2 行でこの効果が得られます。
どう始めるか: アプリ内で Sidebar を含む詳細画面を洗い出し、背景画像(ポスター、カバー、地図)を UIBackgroundExtensionView.contentView に入れ、タイトル・リストは sibling として追加します。必要に応じて automaticallyPlacesContentView をオフにしてレイアウトをカスタマイズします。
4. すべてのカスタムフローティングコンテナに ScrollEdgeElementContainerInteraction を追加する
なぜやる価値があるか: スクロールビュー端の自動ぼかし処理はシステム Bar にしか効きません。カスタムフローティングボタン群は接続しないと、下のテキストとボタンが混ざって読みにくくなります。
どう始めるか: フローティングボタン群やクイックアクションバーをすべてリストアップし、それぞれのコンテナビューに UIScrollEdgeElementContainerInteraction を追加して、対応する scrollView と edge を設定します。
5. ふさわしい場面ではカスタムコントロールを UIGlassEffect でラップする
なぜやる価値があるか: 自前の再生コントロール、トラック選択、バッジが単色背景のままだと、システムのビジュアルから浮いて見えます。UIGlassEffect と UIGlassContainerEffect を使うと Liquid Glass の世界に溶け込みます。
どう始めるか: 一番目立つカスタムフローティングウィンドウをパイロットに選び、UIVisualEffectView でラップして tintColor と isInteractive を設定します。複数要素なら UIGlassContainerEffect に入れてマージのアニメーションを確認します。
関連 Session
- Build a SwiftUI app with the new design — SwiftUI 側の対応実装。Tab、Navigation、Presentation、コントロールの改修を同じトピックでカバーしています。
- Make your UIKit app more flexible — UITab/UITabGroup の適応能力。本セッションの Tab Bar の章と合わせて読むと理解が深まります。
- What’s new in UIKit —
updateProperties()による自動 trait 追跡の仕組みを解説しており、本セッションでも繰り返し参照されています。 - Get to know the new design system — Liquid Glass のデザインランゲージ全体像。UIKit 実装の詳細に対する上流のデザインガイドです。
コメント
GitHub Issues · utterances