モバイル開発におけるSheet — その本質、種類、動作方法

著者: IT Sectr 公開日: 2026-06-10 読了時間: 10 分

Sheetは、メインコンテンツの上に画面下部に表示され、追加のアクションや情報を提供するUIコンポーネントです。Bottom Sheetは最も一般的な種類で、Material Design 3(Google、2024)のガイドラインで定義されています。ダイアログウィンドウとは異なり、Sheetはバックグラウンドとの操作を完全にブロックせず、collapsedおよびexpanded状態をサポートします。モバイルアプリケーションで便利なナビゲーションを構築するには、Sheetの種類と動作を理解することが必要です。

重要ポイント

  • Sheetはメインコンテンツの上に画面下部からスライドアップするUIコンポーネント
  • Bottom Sheetは標準(非モーダル)とモーダルがあり、必須アクション用
  • Material Design 3はドラッグ操作でcollapsedとexpandedの2状態を定義
  • iOSではSheetはUIKitのUISheetPresentationControllerとSwiftUIの.sheetで実装
  • FlutterではBottom SheetはshowBottomSheetとshowModalBottomSheetで作成

モバイルアプリケーションにおけるSheetとは

Sheetは、画面下部からスライドアップし、現在の画面からユーザーを移動させずに追加コンテンツやアクションを表示するサーフェスレベルのUIコンポーネントです。全画面遷移とは異なり、Sheetはコンテキストを保持します。ユーザーは背景画面を確認でき、Sheetがどこから現れたかを理解できます。

Sheetのアーキテクチャは高さ調節可能なコンテナに基づいています。最小状態(collapsed)では、コンテンツの一部のみが表示され、通常はタイトルまたは小さなパネルだけです。ユーザーはSheetを上にドラッグして展開(expanded)したり、下にスワイプして閉じたりできます。この動作は、紙の束の下から物理的なシートを引き出す様子に似ていることから、この名前が付けられました。

GoogleはMaterial Design 3のガイドライン(2024)で、Sheetの使用に関する2つの主要なシナリオを強調しています。メインツールバーに収まらない追加アクションの表示、および別画面に移動せずにフォームや詳細情報を表示することです。iOSでは、AppleがiOS 15からUISheetPresentationControllerを通じてシステムレベルのSheetサポートを追加し、このパターンの普遍性を証明しています。

Bottom Sheetの種類:標準、モーダル、拡張

Material Designは3種類のBottom Sheetを定義しており、それぞれに独自の動作と適用領域があります。適切なタイプを選択することは、ユーザーエクスペリエンスとプラットフォームガイドラインへの準拠に直接影響します。

標準Bottom Sheet

標準Bottom Sheetは非モーダルコンポーネントです。ユーザーはSheetを閉じずに背景画面と操作できます。例えば、背景で商品リストを閲覧しながら、ユーザーはBottom Sheetにフィルターを表示し、パネルを閉じずに変更できます。Sheetはコンテンツに応じて高さを調整します(画面の30%~90%)。

標準Bottom Sheetは背景をブロックせず、メインコンテンツとの操作を許可します。これがモーダルSheetとの主な違いであり、モーダルSheetは続行するために必須のアクションが必要です。追加情報がメインシナリオにとって重要でない場合は、標準Sheetを使用してください。

モーダルBottom Sheet

モーダルBottom Sheetは、ユーザーがSheet内でアクションを実行するまで背景画面との操作をブロックします。このようなSheetは常に展開状態で表示され、ボタン、アクション、または下へのスワイプによる明示的な閉じる操作が必要です。Material Designは、ログインフォーム、確認ダイアログ、重要な設定にモーダルSheetを推奨しています。

Androidでは、モーダルBottom SheetはBottomSheetDialogFragmentを介して実装され、自動的に背景をブロックします。iOSでは、.mediumDetentパラメータを持つUISheetPresentationControllerのモーダルバリアントが同様の動作を提供します。モーダルSheetは、コンテキストがユーザーの注意を必要とする場合にのみ使用する必要があります。

拡張Bottom Sheet

拡張Bottom Sheetは標準とモーダルの特性を組み合わせたものです。collapsed状態では非モーダルとして開始しますが、上にドラッグするとモーダルになります。実際には、ユーザーはまずコンテンツを一目見て、その後Sheetを展開して詳細を確認するか閉じるかを決定できます。

このパターンは特に地図やナビゲーションアプリで人気があります。下部パネルにルートポイントの簡潔な情報が表示され、上にスワイプすると詳細とともに展開されます。Googleマップは、場所やルートに関する情報を表示するために、まさにこの拡張Sheetを使用しています。

Sheetの種類背景ブロック初期状態
標準なしCollapsedカタログのフィルター
モーダルありExpandedログインフォーム
拡張部分的Collapsed場所カード

AndroidのBottom Sheet:Material DesignとJetpack Compose

Android SDKは、従来のViewベースのアプローチから最新のJetpack Composeまで、Bottom Sheetを実装するための複数のAPIを提供しています。Android用Material Componentsライブラリには、BottomSheetDialogFragmentとBottomSheetBehaviorの既成実装が含まれています。

XMLレイアウトでのBottomSheetBehavior

BottomSheetBehaviorは、任意のViewにアタッチして画面上の位置を制御するMaterial Componentsのクラスです。開発者はSTATE_COLLAPSED、STATE_EXPANDED、STATE_HIDDENの3つの状態を設定します。Behaviorはドラッグジェスチャーとアニメーションを自動的に処理します。

kotlin
val sheet = findViewById<View>(R.id.bottom_sheet)
val behavior = BottomSheetBehavior.from(sheet)
behavior.state = BottomSheetBehavior.STATE_COLLAPSED
behavior.peekHeight = 200

Jetpack ComposeでのBottom Sheet

Jetpack Composeは、Material 3のModalBottomSheetコンポーネントを通じて、より宣言的なAPIを提供します。Viewベースのアプローチとは異なり、ComposeではBottom Sheetは状態とコンテンツを受け取るコンポーザブル関数です。Sheetは、ドラッグ時の表示、非表示、高さ変更を自動的にアニメーション化します。

kotlin
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FilterSheet(onDismiss: () -> Unit) {
    ModalBottomSheet(onDismissRequest = onDismiss) {
        Text("フィルター")
        Button(onClick = onDismiss) { Text("適用") }
    }
}

モーダルシナリオのためのBottomSheetDialogFragment

BottomSheetDialogFragmentは、Bottom Sheetとして表示される特殊なDialogFragmentです。モダリティ、ライフサイクル、構成変更を自動的に処理します。開発者はonCreateViewをオーバーライドしてSheetのレイアウトを返すだけです。Googleのドキュメント(Android Developers、2024)によると、BottomSheetDialogFragmentは従来のAndroidでモーダルBottom Sheetに推奨される方法です。

iOSのSheet:UISheetPresentationControllerとSwiftUI

AppleはiOS 15からUISheetPresentationControllerを通じてシステムレベルのSheetサポートを導入しました。それ以前は、開発者はカスタムトランジションまたはサードパーティライブラリを使用して手動でBottom Sheetを実装していました。AppleのネイティブSheetは、定義済みの展開レベルであるdetentsをサポートしています。

UIKitのUISheetPresentationController

UISheetPresentationControllerは、View ControllerをSheetとして表示する組み込みのプレゼンテーションコントローラです。開発者は、Sheetが停止できる高さの値であるdetentsの配列を指定します。iOS 16では任意の高さのカスタムdetentsが追加されました。Appleは主要なdetentsとしてmedium(.medium)とlarge(.large)を推奨しています。

swift
let viewController = MySheetViewController()
if let sheet = viewController.sheetPresentationController {
    sheet.detents = [.medium, .large]
    sheet.prefersGrabberVisible = true
    sheet.preferredCornerRadius = 16
}
present(viewController, animated: true)

SwiftUIの.sheet修飾子

SwiftUIは、Sheetの表示を状態にバインドする.sheet修飾子を提供します。published変数がtrueになると、SwiftUIが自動的にSheetを表示します。SwiftUIはiOS 16で追加された.presentationDetents修飾子を介してdetentsもサポートしています。

swift
struct ContentView: View {
    @State private var showSheet = false

    var body: some View {
        Button("シートを表示") { showSheet = true }
            .sheet(isPresented: $showSheet) {
                FilterView()
                    .presentationDetents([.medium, .large])
            }
    }
}

クロスプラットフォームフレームワークのSheet:FlutterとReact Native

クロスプラットフォームフレームワークもBottom Sheetをサポートしており、ターゲットプラットフォームに応じて動作を適応させています。FlutterとReact Nativeは、さまざまな柔軟性で組み込みおよびカスタム実装を提供しています。

FlutterのBottom Sheet

Flutter SDKには、Bottom Sheetを表示する2つのメソッドがあります。showBottomSheet(標準)とshowModalBottomSheet(モーダル)です。FlutterのMaterial DesignはAndroidと同じ原則に従い、Sheetは下部から表示され、ドラッグをサポートし、高さを調節できます。detentsを使用した拡張動作にはDraggableScrollableSheetが使用されます。

dart
Scaffold.of(context).showBottomSheet((context) {
    return Container(
        padding: EdgeInsets.all(16),
        child: Column(
            children: [
                Text("シートコンテンツ"),
                ElevatedButton(
                    onPressed: () => Navigator.of(context).pop(),
                    child: Text("閉じる")
                )
            ]
        )
    );
})

React NativeのBottom Sheet

React Nativeのコアには組み込みのBottom Sheetコンポーネントがないため、開発者はサードパーティライブラリを使用します。最も人気があるのは@gorhom/bottom-sheetです(GitHubで7000以上のスター、2024年)。スナップポイント、アニメーション、固定ヘッダーをサポートするジェスチャ駆動のBottom Sheetを提供します。このライブラリは、60FPSのパフォーマンスを実現するためにReanimated 2とGesture Handler上に構築されています。

ベストプラクティスと一般的な間違い

Bottom Sheetの適切な使用には、プラットフォームガイドラインの順守と、Sheetが適切なシナリオの理解が必要です。Sheetを設計する際の主要な推奨事項と一般的な間違いを確認しましょう。

Bottom Sheetを使用する場合

Bottom Sheetは、画面上のメインコンテンツに対する補足的なアクションに最適です。フィルター、並べ替え、オプション選択、アイテムの簡単な情報などが典型的なシナリオです。Material Designは、画面全体を占有すべきではないが、Action Sheetやポップアップメニューよりも多くのスペースを必要とするツールにBottom Sheetの使用を推奨しています。

Bottom Sheetを使用すべきでない場合

重要な警告やエラーにBottom Sheetを使用しないでください — これにはダイアログウィンドウが適しています。スクロールが必要な多数の入力フィールドがあるSheetは避けてください。ユーザーがキーボードに到達するのに苦労し、コンテキストを失います。Sheetに7つ以上のアクションアイテムが含まれる場合は、Sheetの代わりに別の画面を検討してください。

間違い:collapsedモードが高すぎる

一般的な間違いは、peekHeight(折りたたまれた状態の高さ)を画面の40%以上に設定することです。ユーザーはSheet全体を見ているのか、それとも展開できるのかがわかりません。Material Designは、コンテンツの顕著な部分を隠したままにしてドラッグを促すために、peekHeightを画面高さの15~30%に設定することを推奨しています。

間違い:iOSでのスワイプジェスチャーの無視

iOSでは、ユーザーは任意の位置から下にスワイプしてSheetを閉じられることを期待しています。このジェスチャーを無効にすると(UISheetPresentationController.prefersEdgeAttachedInCompactHeight)、ユーザーは慣れた方法でSheetを閉じようとしてフラストレーションを感じます。Appleのヒューマンインターフェースガイドライン(2024)は、スワイプして閉じることはiOSユーザーの基本的な期待であると強調しています。

よくある質問

Bottom Sheetとダイアログウィンドウの違いは何ですか?

Bottom Sheetは背景を完全にブロックせず、ドラッグをサポートしますが、ダイアログウィンドウはモーダルで必須のアクションが必要です。Bottom Sheetは補足的なオプションに適しており、ダイアログは重要な確認に適しています。

キーボードと一緒にBottom Sheetを使用できますか?

はい、ただしAndroidマニフェストでadjustResizeまたはadjustPanの設定が必要です。iOSではキーボードが自動的にSheetを持ち上げます。FlutterとReact Nativeでは、正しい配置のためにMediaQueryによる手動処理が必要です。

Bottom Sheetにはいくつのアイテムを配置するのが最適ですか?

推奨されるのは、標準Sheetで5~7個以下のアイテムです。それ以上のコンテンツがある場合は、スクロールまたはカテゴリ分割を使用してください。Material Designは、展開状態で画面高さの90%を超えないようにアドバイスしています。

背景タップ時のSheetの閉じ方を処理するには?

モーダルSheetの場合、AndroidではsetCancelable(true)を、iOSではisModalInPresentation = falseを設定します。Jetpack Composeでは、onDismissRequestが背景タップを自動的に処理します。SwiftUIでは、下へのスワイプがデフォルトの動作です。

Bottom Sheetはアクセシビリティをサポートしていますか?

はい、すべてのネイティブ実装がVoiceOverとTalkBackをサポートしています。FocusManagerがSheetを開くときに正しくフォーカスをSheetに移動し、閉じるときに戻すことを確認してください。カスタム実装では手動のアクセシビリティ設定が必要です。

まとめ

  • Sheetは新しい画面に移動せずに追加コンテンツを表示するため、画面下部からスライドアップするUIコンポーネント
  • 3種類のSheet:標準(非モーダル)、モーダル(背景ブロックあり)、拡張(複合型)
  • Material Design 3はcollapsedとexpandedの状態とドラッグサポートでBottom Sheetを定義
  • AndroidではBottomSheetBehavior、BottomSheetDialogFragment、ComposeのModalBottomSheetで実装
  • iOSではiOS 15以降のUISheetPresentationController(detents)とSwiftUIの.sheet修飾子を使用
  • クロスプラットフォームフレームワークではshowBottomSheet(Flutter)と@gorhom/bottom-sheet(React Native)で利用可能
  • 重要な警告や多数のフィールドがあるフォームにはSheetを避け、別の画面を使用

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください