Push Presentationは、モバイルアプリケーションにおいて新しい画面がナビゲーションスタックの前面に追加されるナビゲーションパターンです。ユーザーはコンテンツを順に進み、システムボタンやスワイプで戻ることができます。Apple Developer, 2025によると、UINavigationControllerは85%のiOSアプリで主要なナビゲーションパターンとして使用されています。Androidでは、同様の機能がFragmentManagerとNavigation ComponentのNavControllerを通じて実装されています。
重要なポイント
Push Presentationは、新しい画面がスタックの先頭に配置され、前の画面がその下のメモリに残るナビゲーションメカニズムです。ユーザーは詳細画面を順に開いてコンテンツを深く掘り下げ、戻るボタンで前のステップに戻ります。
PushナビゲーションのアーキテクチャはLIFO(Last In, First Out)データ構造に基づいています。新しい画面は常にスタックの最後に追加され、削除は先頭からのみ行われます。これにより予測可能な動作が保証されます。ユーザーは戻るボタンが正確に1つ前のステップに戻ることを常に認識しています。ナビゲーションスタックはアプリケーションの複雑さに応じて2〜10+の画面を含むことができます。
Push Presentationは階層型コンテンツを持つアプリケーションの主要なパターンです:ニュースフィード、製品カタログ、マルチレベルメニュー、ドキュメンテーション。Material Designによると、スタックナビゲーションはユーザーが一般から特定へとコンテンツを探索し、各後続の画面がトピックの理解を深めるシナリオに適しています。
ナビゲーションスタックは、各要素が自身のViewControllerまたはFragmentの状態を保存する画面の順序付けられたセットです。Push操作中、新しい画面がスタックに追加され、その出現がアニメーション化され(iOSでは右からのスライド、Androidでは下からのスライドまたはフェード)、アクティブになります。
Pop操作(戻るボタン押下)中、上部の画面がスタックから削除され、破棄されるかメモリに移動し、前の画面がアクティブになります。iOSはデフォルトでポップされたViewControllerを破棄し、メモリを解放します。AndroidはFragmentを再作成せずに復元可能なバックスタックに保存できます。
スタックの深さはパフォーマンスに影響します:スタック内の各画面はメモリを消費します。推奨事項:スタックに10画面以上保持しないでください。深いナビゲーションにはPopToRootを使用するか、新しいルート画面でスタックを再起動してください。AndroidのNavigation ComponentはSavedStateHandleを通じてスタックの状態を自動的に管理します。
UINavigationControllerはUIViewControllerのスタックを管理するiOSのコンテナコントローラーです。現在の画面のタイトルと戻るボタンを含むナビゲーションバーを自動的に表示します。デフォルトのプッシュアニメーションは右から左へのスライドで、ユーザーにコンテンツへの没入感を生み出します。
画面の追加はpushViewController(_:animated:)を介して行われます。削除はpopViewController(animated:)を介して行われます。ルート画面に戻るにはpopToRootViewController(animated:)を使用します。UINavigationControllerはviewControllersプロパティを通じてプログラムによるスタック管理もサポートしています — スタック内のすべてのコントローラーの配列です。
ナビゲーションバーには画面のタイトル、戻るボタン、オプションのアクションボタンが含まれます。iOS 11以降、Large Titles(prefersLargeTitles)により、スクロール時にアニメーションで縮小される拡大フォントでタイトルを表示できます。これによりナビゲーション階層が改善され、ユーザーに現在のセクションが通知されます。
let detailVC = DetailViewController()
detailVC.title = "Item Details"
navigationController?.pushViewController(detailVC, animated: true)
// 前の画面に戻る
navigationController?.popViewController(animated: true)
// ルートに戻る
navigationController?.popToRootViewController(animated: true)
Navigation Componentは宣言的ナビゲーションのためのAndroid Jetpackライブラリです。ナビゲーショングラフ(nav_graph)を通じてフラグメントやCompose画面を管理するNavControllerを提供します。AndroidのPushはiOSと同様で、各新しいFragmentがバックスタックに追加され、戻るボタンで前の画面に戻ります。
NavHostはNavGraphから現在のデスティネーションを表示するコンテナです。NavGraphはすべてのアプリケーション画面とそれらの間の接続を記述するXMLファイルです。遷移はデスティネーションとオプションの引数を指定するactionsを通じて定義されます。Navigation Componentはシステムのバック操作、アニメーション、状態保存を自動的に処理します。
画面間でデータを渡すために、Navigation ComponentはSafe Args — 型安全な引数クラスのコード生成をサポートしています。手動でBundleにデータを配置する代わりに、開発者はNavGraphで引数を宣言し、生成されたDirectionsおよびArgsクラスを通じて受け取ります。Safe Argsは型の不一致エラーを排除し、リファクタリングを簡素化します。
// XMLでのNavGraph定義
<!-- res/navigation/nav_graph.xml -->
@navigation {
NavHost(startDestination = "list") {
composable("list") { ListScreen() }
composable(
"detail/{itemId}",
arguments = listOf(navArgument("itemId") { type = NavType.IntType })
) { DetailScreen(it.arguments()?.getInt("itemId") ?: 0) }
}
}
// プログラムでナビゲート
navController.navigate("detail/42")
Bottom NavigationとPushナビゲーションの組み合わせはモバイルアプリケーションで一般的なパターンです。各Bottom Navigationタブは独自の画面スタックを持ちます。Navigation ComponentはタブごとのNavHostまたは各タブに個別のグラフを持つ単一のNavHostを通じてこれをサポートします。タブの切り替えはプッシュスタックの状態をリセットしません。
Push PresentationとModal Presentationは異なるナビゲーションタスクを解決します。Pushは各新しい画面がコンテキストを深める連続的なコンテンツ閲覧のために設計されています。Modalは完了を必要とする集中タスクのためのものです。実際には、特定のシナリオに適したパターンを選ぶことが重要です。
主な選択基準:ユーザーがコンテキストを失わずに自由に戻れる必要がある場合 — Pushを選択します。タスクが一時的でメインコンテンツ(フォーム、認証)をブロックする場合 — Modalを使用します。同じ画面でのパターンの混合(Modal内のPush)は許容されますが、明確な視覚的階層が必要です。
よくある間違いは、論理的にメインフローの一部である画面シーケンスにModalを使用することです。例えば、注文作成ウィザード(ステップ1→ステップ2→ステップ3)は、モーダルウィンドウのチェーンよりもモーダルコンテナ内のPushを使用して実装する方が良いです。これによりナビゲーション階層と戻りの予測可能性が保持されます。
両方のプラットフォームでのPushナビゲーションの完全な実装を見てみましょう。Swiftの例は、プログラムによるスタック管理とディープリンク処理を備えたUINavigationControllerを示しています。Kotlinの例は、NavHost、引数、アニメーションを備えたNavigation Componentを示しています。
class ListViewController: UIViewController {
func showDetail(_ itemId: Int) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let detailVC = storyboard.instantiateViewController(
withIdentifier: "DetailViewController"
) as! DetailViewController
detailVC.itemId = itemId
navigationController?.pushViewController(detailVC, animated: true)
}
}
class DetailViewController: UIViewController {
var itemId: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
title = "Item #\(itemId)"
}
}
@Composable
fun PushNavigationApp() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "list") {
composable("list") {
ListScreen(
onItemClick = { id -> navController.navigate("detail/$id") }
)
}
composable(
"detail/{itemId}",
arguments = listOf(navArgument("itemId") { type = NavType.IntType })
) { backStackEntry ->
val itemId = backStackEntry.arguments()?.getInt("itemId") ?: 0
DetailScreen(itemId = itemId, onBack = { navController.popBackStack() })
}
}
}
例は基本的なPushナビゲーションを示しています:リスト→詳細。iOSは手動データ受け渡しでストーリーボードとUINavigationControllerを使用します。Androidは型安全な引数と自動バックスタック管理でNavHostを使用します。両方のアプローチがディープリンク、カスタムアニメーション、回転時の状態保存をサポートしています。
よくある質問
Pushは戻るボタン付きでUINavigationControllerスタックに画面を追加します。Presentは戻るボタンなしでモーダルウィンドウを開きます — ユーザーが明示的に閉じる必要があります。Pushは連続的なコンテンツに適し、Presentは集中タスクに適しています。SwiftUIでは、PushはNavigationLinkに、Presentは.sheetに対応します。
Navigation Componentは特定のポイントまでのpopBackStackメソッドとスタッククリアのためのpopUpToを提供します。スタックオーバーフローを防ぐには、navigateの前にpopUpTo(startDestination) { inclusive = true }を使用します。これによりスタックに同時に5〜7画面以上含まれないことが保証されます。
はい、PushとModalの組み合わせは標準的なパターンです。例:リスト→詳細にPush→認証にModal。推奨事項:Modal内にPushをネストしないでください。モーダルウィンドウにスタックナビゲーションを含めるべきではありません。モーダルウィンドウ内で画面シーケンスが必要な場合は、モーダルコンテナ内でPushを使用してください。
Pushナビゲーションのディープリンクは特定の画面でアプリを開きます。iOSはUINavigationControllerとURLスキームおよびUniversal Linksを使用します。AndroidはNavDeepLinkとIntent Filtersを使用します。どちらの場合も、システムがリンクを解析し、ターゲット画面へのナビゲーションスタックを作成し、戻る機能を保持します。
iOSはUINavigationControllerDelegateを通じてカスタマイズ可能な標準スライドアニメーションを使用します。Android Navigation ComponentはXMLリソース(slide_in_right、slide_out_left)を通じてカスタムアニメーションをサポートしています。Composeの場合は、animateItemPlacement修飾子とともにAnimatedNavHostを使用してください。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。