モバイル開発におけるモーダル表示:その概要と画面の種類

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

モーダル表示は、現在のコンテキストの上に画面を表示し、以前のインターフェースとの操作をブロックする方法です。モバイル開発では、モーダルウィンドウは集中タスク(データ入力、アクション確認、認証、オプション選択)に使用されます。Apple HIG、2025によると、モーダル表示はアプリケーションのナビゲーションシナリオの20%を超えないようにする必要があります。Androidでは、モーダル性はDialogFragment、BottomSheet、および特定の起動フラグを持つActivityを通じて実装されます。

重要なポイント

  • モーダル表示は、モーダルウィンドウが閉じられるまで以前のコンテンツとの操作をブロックする画面表示テクニックです。
  • iOSはUIModalPresentationStyleを.fullScreen、.pageSheet、.formSheet、.automaticのバリエーションで使用します。
  • AndroidはDialogFragment、BottomSheetDialogFragment、Intentフラグ付きActivityを通じてモーダル性を実装します。
  • SwiftUIは宣言的モーダル表示のための.sheetおよび.fullScreenCoverモディファイアを提供します。
  • Jetpack Composeはモーダルインターフェース作成にDialogとModalBottomSheetを使用します。

モーダル表示とは?

モーダル表示は、現在の画面の上に新しい画面が表示され、一時的に親コンテンツとの操作をブロックするナビゲーションパターンです。ユーザーは以前の状態に戻るために、モーダルタスク(キャンセル、保存、閉じる)を明示的に完了する必要があります。

モーダル性は認知タスクを解決します。ユーザーの注意をインターフェースの他の部分から気を散らすことなく、単一のアクションに集中させます。これは、登録フォーム、確認ダイアログ、ファイル選択、サードパーティサービスによる認証にとって極めて重要です。AppleのHuman Interface Guidelinesは、続行する前に完了が必要なタスクにのみモーダル性を使用することを推奨しています。

Webのモーダルウィンドウとは異なり、モバイルのモーダル表示は全画面(画面全体を占有)または部分表示(Page Sheet、Bottom Sheet)にすることができます。タイプの選択は、タスクのコンテキストとプラットフォームの慣例によって異なります。iOSはほとんどのシナリオでPage Sheetを採用し、Full Screenはビデオプレーヤーやフォトエディターに残しています。

Push表示(スタックナビゲーション)は、ナビゲーションスタックに画面を追加し、自動的に戻るボタンを表示します。ユーザーはいつでも前の画面に戻ることができます。一方、モーダル表示は明示的な完了が必要です。戻るボタンは存在しないか、前の画面に戻る代わりにモーダルウィンドウを閉じます。

モーダル表示とPush表示の主な違い:モーダル表示はデータを失うことなく後方ナビゲーションをブロックし、閉じるためのアクション(Save、Cancel、Done)が必要で、通常は個別のタスクを表します。Push表示はナビゲーション階層を保持し、自動的に戻るボタンを追加し、順次コンテンツ表示に適しています。

特徴モーダル表示Push表示
戻るブロックはい、明示的なアクションが必要いいえ、戻るボタンは常に利用可能
典型的な使用法フォーム、認証、選択詳細表示、ナビゲーション
アニメーション下から上へ(iOS)、スライド(Android)右から左へ(iOS)
ナビゲーションスタックメインスタックに追加されないスタックに追加される

実際には、ModalとPushの選択はコンテキストによって異なります。続行する前にユーザーが完了する必要があるタスクにはモーダル性を使用し、順次コンテンツ探索にはPushを使用することをお勧めします。同じ画面でパターンを混在させると混乱を招き、UXが低下します。

iOSのモーダル表示:UIKitとSwiftUI

iOSUIModalPresentationStyle列挙型を通じて複数のモーダル表示スタイルを提供します。UIKitは.fullScreen(全画面)、.pageSheet(上部マージン付きカード)、.formSheet(iPadの中央ウィンドウ)、.automatic(コンテキストに基づいてシステムが選択)をサポートしています。iOS 13以降、デフォルトスタイルは.automaticになり、iPhoneでは.pageSheetを選択します。

UIViewController.present

モーダル表示のための基本的なUIKitメソッドはpresent(_:animated:completion:)です。メソッドを呼び出すコントローラーがpresentingViewControllerになり、新しいコントローラーがpresentedViewControllerになります。閉じるにはdismiss(animated:completion:)を使用します。SwiftUIは同様の動作のために.sheetモディファイアを提供します。

SwiftUI .sheet

SwiftUIの宣言的アプローチは.sheetおよび.fullScreenCoverモディファイアを使用します。前者はPage Sheetを作成し、後者は全画面モーダル表示を作成します。どちらも、モーダルウィンドウの表示を制御するBoolまたは識別可能なオブジェクトへのバインディングを受け入れます。バインディングがfalseに設定されるか、環境からdismissが呼び出されると閉じます。

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

    var body: some View {
        Button("フォームを開く") {
            showModal = true
        }
        .sheet(isPresented: $showModal) {
            RegistrationForm()
        }
    }
}

struct RegistrationForm: View {
    @Environment(\.dismiss) private var dismiss

    var body: some View {
        Button("保存") { dismiss() }
    }
}

Androidのモーダル表示:FragmentとCompose

AndroidにはiOSのようなモーダル表示のための単一APIはありません。代わりに、プラットフォームはいくつかのメカニズムを提供しています:ダイアログウィンドウ用のDialogFragment、下部パネル用のBottomSheetDialogFragment、モーダル画面用のNEW_TASKおよびCLEAR_TOPフラグ付きActivity。Jetpack Composeはすべてのタイプのモーダルウィンドウに対して統一されたDialogコンポーネントを導入しました。

DialogFragment

DialogFragmentはAndroid SDKのモーダルウィンドウの基本クラスです。ダイアログのライフサイクルを管理し、画面回転を処理し、状態を保存します。フラグメントはナビゲーションスタックをブロックせずにActivityの上に表示されます。閉じるにはdismiss()を使用するか、setCancelable(true)の場合はダイアログ領域外をタップします。

モーダルボトムシート

BottomSheetDialogFragmentは、下部から上昇するパネルとしてモーダルウィンドウを表示します。このパターンはMaterial Designでオプション選択、共有、クイックアクションのために人気があります。BottomSheetは固定高さまたは拡張可能(ピーク高さ+全高さ)にすることができます。Composeでは、Material3ライブラリのModalBottomSheetが使用されます。

kotlin
@Composable
fun ModalScreen(onDismiss: () -> Unit) {
    Dialog(onDismissRequest = onDismiss) {
        Card(
            modifier = Modifier.padding(16.dp)
        ) {
            Column {
                Text("モーダルフォーム", style = MaterialTheme.typography.headlineSmall)
                Button(onClick = onDismiss) {
                    Text("閉じる")
                }
            }
        }
    }
}

モーダル表示のベストプラクティス

モーダルウィンドウは強力なUXツールですが、過剰に使用するとユーザー体験が低下します。Apple HIGとGoogle Material Designは推奨事項で一致しています:モーダル性は集中タスクに使用し、全ナビゲーションアクションの20%を超えないようにする必要があります。

モーダル表示を使用するタイミング

モーダルウィンドウは以下のシナリオに適しています:データ入力(登録フォーム、プロフィール)、確認(削除、送信)、選択(日付ピッカー、ファイルマネージャー)、認証(OAuth、Firebase Auth)。タスクが30秒未満でコンテキストブロックが必要な場合は、モーダル性を選択してください。

避けるべきこと

モーダル表示を次の用途に使用しないでください:順次コンテンツ表示(Pushを使用)、エラー表示(ToastまたはSnackbarを使用)、ユーザーの明示的な要求なしの広告やプロモーション。 Material Designはネストされたモーダルウィンドウを避けることを推奨しています。これはユーザーの混乱を招き、ナビゲーション階層を乱すためです。

テキストフィールドのあるモーダルウィンドウの場合は、キーボードフォーカス損失を必ず処理してください。キーボードが表示されたとき、モーダルウィンドウは上に移動して、ユーザーが入力中のテキストを確認できるようにする必要があります。iOSのUIKeyboardWillShowNotificationとAndroidのadjustResizeがこのタスクを解決します。

SwiftとKotlinのコード例

両方のプラットフォームでのモーダル表示の実装を見てみましょう。Swiftの例は、閉じる処理のためのデリゲート付きUIModalPresentationStyle.pageSheetの設定を示しています。Kotlinの例は、カスタムレイアウトと状態保存を備えたDialogFragmentを示しています。

swift
let modalVC = ModalViewController()
modalVC.modalPresentationStyle = .pageSheet

if let sheet = modalVC.sheetPresentationController {
    sheet.detents = [.medium(), .large()]
    sheet.prefersGrabberVisible = true
}

modalVC.presentationController?.delegate = self
present(modalVC, animated: true)

// MARK: - UIAdaptivePresentationControllerDelegate
extension ViewController: UIAdaptivePresentationControllerDelegate {
    func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
        print("モーダルが閉じられました")
    }
}
kotlin
class ModalDialogFragment : DialogFragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_modal, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        view.findViewById<Button>(R.id.closeButton).setOnClickListener {
            dismiss()
        }
    }
}

よくある質問

Pushではなくモーダル表示をいつ使用すべきですか?

続行する前にユーザーが完了する必要がある集中タスク(フォーム、確認、認証)にはモーダル表示を使用してください。Pushは、ユーザーが自由に戻れる順次コンテンツ表示に適しています。モーダルウィンドウには内部にナビゲーションを含めるべきではありません。

iOSではどのモーダル表示スタイルを選ぶべきですか?

iOS 13以降、デフォルトの.automaticスタイルはiPhoneで.pageSheetを選択します。.pageSheetはほとんどのシナリオ(フォーム、詳細)に適しています。.fullScreenはメディアコンテンツ(ビデオ、フォトエディター)用です。.formSheetは中央ウィンドウが必要なiPadアプリ用です。

Jetpack Composeでモーダルウィンドウを実装するには?

Jetpack Composeは、シンプルなモーダルウィンドウ用のDialogコンポーネントと、下部パネル用のModalBottomSheetを提供します。DialogはonDismissRequestとComposeスタイルのコンテンツを受け入れます。状態保存にはダイアログ内でrememberSaveableを使用してください。

モーダルウィンドウを互いにネストできますか?

Apple HIGおよびMaterial Designはネストされたモーダルウィンドウを推奨していません。ユーザーが別のモーダルウィンドウの上にモーダルウィンドウを開くと、コンテキストを失い、階層について混乱する可能性があります。ネストする代わりに、単一のモーダルウィンドウでステップインジケーターまたはウィザードパターンを使用してください。

データ損失を伴うモーダルウィンドウの閉じ方を処理するには?

iOSではUIAdaptivePresentationControllerDelegate(presentationControllerShouldDismissメソッド)、AndroidではOnBackPressedDispatcherを使用してください。未保存の変更がある場合は、オプション(保存、変更を破棄、画面に留まる)を含むAlertDialogを表示します。これにより、ユーザーによる偶発的なデータ損失を防ぎます。

まとめ

  • モーダル表示は、タスクが完了するまで親コンテンツとの操作をブロックするナビゲーションパターンです。
  • iOSはUIModalPresentationStyleによる.fullScreen、.pageSheet、.formSheetとSwiftUIの.sheetをサポートしています。
  • AndroidはDialogFragment、BottomSheet、Jetpack ComposeのDialogを通じてモーダル性を実装します。
  • モーダルは、後方ナビゲーションをブロックし、閉じるための明示的なアクションを必要とする点でPushと異なります。
  • モーダルウィンドウはナビゲーションシナリオの20%を超えてはならず、ネストしてはいけません。
  • モーダルウィンドウを閉じるときのデータ損失は、デリゲートと確認ダイアログによって防止する必要があります。
  • 標準的なモーダルタスクには、iOSではPage Sheet、AndroidではDialogFragmentを選択することをお勧めします

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

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

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

こちらもお読みください