はじめに

こんにちは!システム開発部Yです。

WWDC2025では、「Liquid Glass」という新しいデザインスタイルが導入されました。
一時的に適用を回避するためのフラグも用意されていますが、この回避フラグは来年には廃止される予定です。
つまり、今後1年以内にLiquid Glassへの対応を完了させる必要があるということです。

以下では、そのLiquid Glass対応について、WWDCセッションの内容をもとに整理しました。
詳細は各セッションをご参照ください。

https://developer.apple.com/jp/videos/play/wwdc2025/284

目次

セッション内容

Liquid Glass

Appleは美しい新しいデザインを導入し、システム全体にわたって素材やコントロールの外観、操作性を刷新しました。
この新しいデザイン素材が「Liquid Glass」と呼ばれるもので、半透明でダイナミック、そして躍動感のある表現が特徴です。

Tab views and split views

新しいデザインのタブバーは、コンテンツの上に浮かぶように表示されます。
スクロール時には自動的に最小化され、ユーザーがコンテンツにより集中できるよう設計されています。

スクロール時にタブバーを最小化するには、tabBarMinimizeBehavior を設定します。
ここでは .onScrollDown を指定しており、下方向にスクロールするとタブバーが最小化されます。
反対方向にスクロールすると、タブバーが再び拡張されます。

tabBarController.tabBarMinimizeBehavior = .onScrollDown

タブバーの上にアクセサリビューを表示することができます。
タブバーが最小化されると、アクセサリビューの位置が下がり、タブバーの横に表示されます。
contentView を使用して UITabAccessory を作成します。
続いて、UITabBarControllerbottomAccessory プロパティに設定します。

// Add a bottom accessory
let nowPlayingView = NowPlayingView()
let accessory = UITabAccessory(contentView: nowPlayingView)
tabBarController.bottomAccessory = accessory

アクセサリがタブバーの横に表示される際は、表示スペースが狭くなります。
そのため、限られたスペース内で表示できるよう、一部のメディアコントロールは自動的に非表示になります。
tabAccessoryEnvironment 特性の変更を監視するように登録します。
この特性を使用して、アクセサリビューがタブバーと並んで表示されているかを確認し、必要に応じてビューを更新します。

// Update the accessory with the trait
registerForTraitChanges([UITraitTabAccessoryEnvironment.self]) { (view: MiniPlayerView, _) in
    let isInline = view.traitCollection.tabAccessoryEnvironment == .inline
    view.updatePlayerAppearance(inline: isInline)
}

updateProperties を使用して、変更を監視し、アクセサリビューを更新することもできます。


// Automatic trait tracking with updateProperties()
override func updateProperties() {
    super.updateProperties()
    let isInline = traitCollection.tabAccessoryEnvironment == .inline
    updatePlayerAppearance(inline: isInline)
}

ガラスのような外観を持つサイドバーやツールバーの背景をシームレスに拡張したい場合は、UIBackgroundExtensionView を使用します。
このビューは、Safe Area の外までコンテンツを自動的に延長し、サイドバーの端やステータスバー領域まで自然につながるデザインを実現します。

この効果を追加するには、まず UIBackgroundExtensionView を作成し、その contentView プロパティに画像ビューを割り当てます。
コンテンツビューにレイアウト制約を設定する場合は、automaticallyPlacesContentViewfalse に設定します。
最後に、その拡張ビューを対象のビューに追加します。

let posterImageView = UIImageView(image: ...)

let extensionView = UIBackgroundExtensionView()
extensionView.contentView = posterImageView
extensionView.automaticallyPlacesContentView = false
view.addSubview(extensionView)

let detailsView = ShowDetailsView()
view.addSubview(detailsView)

Auto Layout の制約を使用して、画面上にイメージビューを配置します。
サイドバーの下は extensionView によって拡張表示されるため、コンテンツは Safe Area までの範囲に収まるよう制約を追加します。

posterImageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.active([
  posterImageView.topAnchor.constraint(equalTo: extensionView.topAnchor),
  posterImageView.leadingAnchor.constraint(equalTo: extensionView.safeAreaLayoutGuide.leadingAnchor),
  posterImageView.trailingAnchor.constraint(equalTo: extensionView.safeAreaLayoutGuide.trailingAnchor),
  posterImageView.bottomAnchor.constraint(equalTo: extensionView.safeAreaLayoutGuide.bottomAnchor),
])

ナビゲーションバーとツールバーにも、新しい Liquid Glass の外観が適用されます。

画像ボタンや複数のアイテムを持つボタングループは、同じガラス背景を共有します。
一方で、テキストボタンに加えて、システムの「完了」ボタンや「閉じる」ボタンなどの主要なボタンは、それぞれ個別のガラス背景を使用します。

ナビゲーションバーを設定するには、すべての UIBarButtonItemnavigationItemrightBarButtonItems に直接割り当てます。

navigationItem.rightBarButtonItems = [
    doneButton,
    flagButton,
    folderButton,
    infoButton,
    shareButton,
    selectButton
]

アイテムをさらにグループ化するには、.fixedSpace を使用します。
例では、「共有」ボタンと「詳細」ボタンをさらにグループとしてまとめています。

navigationItem.rightBarButtonItems = [
    doneButton,
    flagButton,
    folderButton,
    infoButton,
    .fixedSpace(0),
    shareButton,
    selectButton
]

ボタンの tintColor を設定することで、表示色を変更できます。
以下の例では、フラグのシンボルのみをオレンジ色に変更しています。

// Custom style
let flagButton = UIBarButtonItem(image: UIImage(systemName: "flag.fill"))
flagButton.tintColor = .systemOrange
flagButton.style = .prominent

navigationItem.rightBarButtonItems = [
    doneButton,
    flagButton,
    folderButton,
    infoButton,
    .fixedSpace(0),
    shareButton,
    selectButton
]

ボタンの背景に色を付けたい場合は、style.prominent に設定します。

let flagButton = UIBarButtonItem(image: UIImage(systemName: "flag.fill"))
flagButton.tintColor = .systemOrange

ツールバーのボタンを等間隔に配置するには、flexibleSpace を使用します。

let flexibleSpace = UIBarButtonItem.flexibleSpace()
toolbarItems = [
   .init(image: UIImage(systemName: "location")),
   flexibleSpace,
   .init(image: UIImage(systemName: "number")),
   flexibleSpace,
   .init(image: UIImage(systemName: "camera")),
   flexibleSpace,
   .init(image: UIImage(systemName: "trash")),
]

ボタンのガラス背景を連続して表示するには、hidesSharedBackgroundfalse に設定します。

let flexibleSpace = UIBarButtonItem.flexibleSpace()
flexibleSpace.hidesSharedBackground = false

Title area updates

iOS 26 では、UINavigationItemsubtitle を使用して、ナビゲーションバーのタイトル下にサブタイトルを追加できるようになりました。

navigationItem.title = "Inbox"
navigationItem.subtitle = "49 Unread"

未読メールの件数が、ナビゲーションバーに表示されています。

navigationItem.title = "Inbox"
navigationItem.largeSubtitleView = filterButton

Review bar customizations

iOS 26 では、ナビゲーションバーの背景がデフォルトで半透明になりました。
ナビゲーションバーやツールバーの下にあるスクロールビューには、ぼかしなどの映像効果が自動的に適用されます。
この効果は「エッジエフェクト(Edge Effect)」と呼ばれます。

この新しいエッジエフェクトが適用されるのは、システムバーだけではありません。
任意の場所にエッジエフェクトを追加することもできます。

重なっているボタンの下にエッジエフェクトを挿入するには、UIScrollEdgeElementContainerInteraction を作成し、contentScrollView とエッジを割り当てます。
その後、このインタラクションを buttonsContainerView に追加します。

let interaction = UIScrollEdgeElementContainerInteraction()
interaction.scrollView = contentScrollView
interaction.edge = .bottom

buttonsContainerView.addInteraction(interaction)

スクロールビューのエッジエフェクトの境界線を強調することもできます。
これを有効にするには、エッジエフェクトのスタイルを .hard に設定します。

scrollView.topEdgeEffect.style = .hard

Content backswipe

iOS 26 では、コンテンツエリア上でもスワイプで戻る操作ができるようになりました。
バックスワイプジェスチャは、他の競合するインタラクションを自動的に検出して処理を調整します。
また、スワイプアクションの実行中はコンテンツをバックスワイプできません。
コンテンツのバックスワイプよりもカスタムジェスチャを優先させる場合は、UINavigationController#interactiveContentPopGestureRecognizer  でエラー要件を設定する必要があります。

Presentations

メニューやポップオーバーなどが Liquid Glass ボタンから表示される場合、そのボタンはオーバーレイに変形します。
メニューにはこの動作が自動的に適用されます。
ポップオーバーの場合は、ソースが barButtonItem のときにこの新しいアニメーションが適用されます。

alertController.popoverPresentationController?.sourceItem = barButtonItem

シートにこの効果を適用するには、新しいズームトランジションを使用します。
viewControllerpreferredTransition.zoom に設定し、ソースとなる barButtonItem をクロージャで返します。

viewController.preferredTransition = .zoom { _ in 
     folderBarButtonItem
}

Action Sheet

iPad のアクションシートは、ソースビューに固定されて表示されます。
iOS 26 以降では、iPhone でも同様の動作となり、元のビューの上に直接表示されます。
alertControllerpopoverPresentationController で、sourceItem または sourceView を設定します。
ソースを指定していない場合、アクションシートは画面中央に表示され、キャンセルボタンが自動的に追加されます。

alertController.popoverPresentationController?.sourceItem = barButtonItem

iOS 26 からは、アプリのニーズに合わせて検索フィールドを自由に配置できるようになりました。
navigationItem.searchBarPlacementBarButtonItem を追加して、検索フィールドを設定します。

toolbarItems = [
    navigationItem.searchBarPlacementBarButtonItem,
    .flexibleSpace(),
    addButton
]

iPad では、検索フィールドをナビゲーションバーの右端に配置します。
この配置は Split View 構成に適しています。
この動作を有効にするには、navigationItemのsearchBarPlacementAllowsExternalIntegrationtrue に設定します。

navigationItem.searchBarPlacementAllowsExternalIntegration = true

ビューの切り替え中にも検索を行えるようにするには、UITabBarController を使用します。
検索専用のタブを右端に追加できるようになりました。
検索ボタンをタップすると拡張され、検索フィールドが表示されます。
このとき、他のボタンは自動的に縮小されます。
デフォルトでは、候補のいずれかを選択するか、検索フィールドをタップして検索を開始します。

検索タブがタップされたときに、検索フィールドを自動的に有効にするには、
このタブのautomaticallyActivatesSearchをtrueに設定します。

searchTab.automaticallyActivatesSearch = true

iPad で検索バーを中央に配置するには、preferredSearchBarPlacement.integratedCentered を指定します。
タブバーが表示されている場合、検索バーはその下に配置されます。

navigationItem.preferredSearchBarPlacement = .integratedCentered

Controls

iOSのコントロールのデザインが一新されました。使い慣れた操作性は変わりません。

UISwitch などのコントロールは、サイズがわずかに変更されています。
スイッチやセグメントコントロールなどには、インタラクション用の新しい Liquid Glass の外観が自動的に適用されます。

既存のボタンスタイルに加えて、UIButtonConfiguration により 2 つの新しい Liquid Glass の外観を利用できるようになりました。
標準の Liquid Glass を適用するには、.glass() 構成を使用します。
アプリのアクセントカラーが反映された Liquid Glass を適用するには、.prominentGlass() を使用します。

button.configuration = .glass()

tintedButton.configuration = .prominentGlass()

スライダーでは、Liquid Glass 効果に加えて、操作時に勢いと伸縮性のあるアニメーションが適用されます。
iOS 26 では、TrackConfiguration によりスライダー上に目盛りを表示できるようになりました。
たとえば、速度スライダーの値を 5 段階に制限したい場合は、trackConfigurationallowsTickValuesOnly を有効にし、目盛りを 5 に設定します。
また、neutralValue を設定することで、任意の位置にスライダーフィルを配置できます。

slider.trackConfiguration = .init(allowsTickValuesOnly: true,
                                  neutralValue: 0.2,
                                  numberOfTicks: 5)

進捗状況バーのようなスタイルにすることもできます。
メディア再生に適しています。

slider.sliderStyle = .thumbless

Custom elements

Liquid Glass は、UIBlurEffect などの他の視覚効果とは異なり、インタラクティブなレイヤーとして設計された特別なエフェクトです。
そのため、アプリ内でもメインコントロールなどの重要な要素に限定して使用することが推奨されます。
最高のユーザー体験を提供するために、可能な限りシステム標準のビューやコントロールを使用することをおすすめします。

カスタムビューで Liquid Glass を使用するには、UIVisualEffectView と新しい UIGlassEffect を組み合わせます。
アニメーションブロック内でこの効果を設定します。
デフォルトでは、カプセル型の形状が適用されます。

// Adopting glass for custom views

let effectView = UIVisualEffectView()
addSubview(effectView)

let glassEffect = UIGlassEffect()
// Animating setting the effect results
// in a materialize animation
UIView.animate {
    effectView.effect = glassEffect
}

この形状をカスタマイズするには、新しい cornerConfiguration を使用します。

UIView.animate {
    effectView.cornerConfiguration = .fixed(8)
}

Liquid Glass の外観には、ダークモードとライトモードの 2 種類があります。
選択された overrideUserInterfaceStyle に応じて、自動的に切り替わります。

UIView.animate {
    view.overrideUserInterfaceStyle = .dark
}

既存の Liquid Glass コンテナに新しい Liquid Glass を追加すると、その外観が自動的に更新されます。

// Adding glass to an existing glass container

let container = UIVisualEffectView()
container.effect = UIGlassEffect()

container.contentView.addSubview(effectView)

コンテナに合わせてコーナーを自動的に調整するには、.containerRelativecornerConfiguration を使用します。
このビューをコンテナのコーナーに近づけると、cornerRadius が自動的に調整されます。

// Container relative corners

UIView.animate {
    effectView.cornerConfiguration = .containerRelative()
    effectView.frame.origin = CGPoint(x: 10, y: 10)
}

コーナーから遠ざけるとコーナー半径が小さくなり同心性が自動的に維持されます。

// Container relative corners

UIView.animate {
    effectView.frame.origin = CGPoint(x: 30, y: 30)
}

Liquid Glass の外観は、サイズに応じて自動的に調整されます。
サイズが大きいほど不透明になり、小さいほど透明になります。
また、ライトモードとダークモードは背景に合わせて自動的に切り替わり、コントラストが最適化されます。

// Glass adapts based on its size

UIView.animate {
    view.overrideUserInterfaceStyle = .light
    effectView.bounds.size = CGSize(width: 250, height: 88)
}

UIView.animate {
    effectView.bounds.size = CGSize(width: 150, height: 44)
}

ラベルやイメージなどのコンテンツを追加するには、visualEffectViewcontentView を使用します。
textColor に基づいて、ラベルの色が自動的に最適化され、より鮮やかに表示されます。

// Adding content to glass views

let label = UILabel()
label.text = "WWDC25"
label.textColor = .secondaryLabel

effectView.contentView.addSubview(label)

重要なビューをハイライトするには、Liquid Glass の tintColor を設定します。

// Applying tint color to glass

let glassEffect = UIGlassEffect()
glassEffect.tintColor = .systemBlue

UIView.animate {
    effectView.effect = glassEffect
    label.textColor = .label
}

ボタンなどのインタラクティブなシステム要素は、ユーザー操作に反応します。
同じ効果をカスタムビューに追加するには、glassEffectisInteractivetrue に設定します。

// Enabling interactive glass behavior

let glassEffect = UIGlassEffect()
glassEffect.isInteractive = true

effectView.effect = glassEffect

Liquid Glass は、複数の異なる形状をシームレスに融合できます。
Liquid Glass ビューを動的にマージするには、UIGlassContainerEffect を使用します。
UIVisualEffectView を構成して Liquid Glass ビューを作成し、それらをサブビューとしてコンテナの contentView に追加します。
両者の間にスペースがある場合は、2 つの独立したビューとして表示されます。

// Adding glass elements to a container

let container = UIGlassContainerEffect()
let containerView = UIVisualEffectView(effect: container)

let glassEffect = UIGlassEffect()
let view1 = UIVisualEffectView(effect: glassEffect)
let view2 = UIVisualEffectView(effect: glassEffect)

containerEffectView.contentView.addSubview(view1)
containerEffectView.contentView.addSubview(view2)

2 つのビューを近づけると、水滴のように結合されます。
互いに影響を与え合う距離を指定するには、UIGlassContainerEffectspacing を使用します。

// Adjusting the container spacing

let containerEffect = UIGlassContainerEffect()
containerEffect.spacing = 20
containerEffectView.effect = containerEffect

重なり合うフレームをアニメーション化すると、2 つの Liquid Glass ビューが結合して 1 つの形状になります。

Liquid Glass を複数の要素に分割するには、まずアニメーションを使用せずに、それらを同じ位置に追加します。
次に、それらをまとめてアニメーション化します。

// Dividing glass into multiple views

UIView.performWithoutAnimation {
    for view in finalViews {
        containerEffectView.contentView.addSubview(view)
        view.frame = startFrame
    }
}

UIView.animate {
    for view in finalViews {
        view.frame = finalFrame(for: view)
    }
}

まとめ

WWDC2025で発表されたiOS 26における、Liquid GlassによるUIKitアプリの作成についてまとめました。

ナビゲーションバーやボタン、ツールバーなどに標準で適用されるほか、
UIVisualEffectViewUIGlassEffect を組み合わせれば、カスタムビューでも簡単に利用可能です。
複数のビューを近づけると水滴のように融合するなど、動きにもこだわりが感じられます。

アプリのメイン操作や印象的な部分など、要所に取り入れるのがベストです。
この記事が少しでも参考になれば幸いです。詳細はWWDCのセッションをご参照ください。

参考



ギャップロを運営しているアップフロンティア株式会社では、一緒に働いてくれる仲間を随時、募集しています。 興味がある!一緒に働いてみたい!という方は下記よりご応募お待ちしております。
採用情報をみる