2026年のAndroidにおけるedge-to-edgeとpredictive back:今や必須になったことと、UIを壊さない方法
edge-to-edgeはAPI 35以降で強制になり、predictive backはデフォルトのジェスチャーになった。Composeのinsets、WindowInsets、PredictiveBackHandlerについての実践ガイド。
このサイクルで、2つのAndroid UIの変更がオプションではなくなった。API 35以降をターゲットにするアプリはedge-to-edgeが強制される——もはやシステムに不透明なバーを描画させるという選択肢を選ぶことはできない。そしてpredictive back、つまり確定する前にどこへ向かうかをプレビューする戻るスワイプジェスチャーは、実験的なフラグではなく、ジェスチャーナビゲーション端末におけるデフォルトの操作になった。どちらも再設計ではない。どちらも、それ向けに作られていないUIを目に見える形で壊す。そして失敗の仕方はどちらも同じだ——テストしたエミュレーターでは問題なく動くのに、ノッチ付きや三ボタンナビゲーションをオフにした実機では壊れて見える。
これが実際に変わった内容と、両方の変更の下で5つのアプリの画面を正しく保つCompseコードだ。
edge-to-edgeはもはや選択肢ではない
API 35以前は、enableEdgeToEdge()は特定の画面のためにオプトインするものだった——半透明のステータスバーの下にコンテンツを流したいアプリにとっての、ちょっとした追加機能だった。API 35をターゲットにすると、その選択肢はなくなる。Window.setDecorFitsSystemWindows(false)の動作が強制され、システムバーは透明になり、あなたが何も呼び出していなくても、ルートコンテンツはその背後に描画される。
実際の影響はこうだ。ステータスバーとナビゲーションバーが自分専用のスペースを確保していると想定していたレイアウトはすべて、物理ピクセルのゼロからコンテンツが始まることになる。上部のアプリバーのタイトルは時計の下に埋もれる。下部のナビゲーションバーのアイコンはジェスチャーピルの下に埋もれる。これは見た目の仕上げの問題ではない——実機では、ユーザーがUIの一番下の行をタップできなくなることを意味する。
解決策は「どこにでもパディングを追加する」ことではない。WindowInsetsを正しい境界に、一度だけ適用することだ。そうすればシステムバーは、コンテンツが必要とする場所にだけ正確にスペースを確保し、それ以外の場所には確保しない。
setContent {
AppTheme {
Scaffold(
contentWindowInsets = WindowInsets.safeDrawing,
topBar = { TopAppBar(title = { Text("Stocky") }) },
) { padding ->
LazyColumn(contentPadding = padding) {
items(pantryItems) { PantryRow(it) }
}
}
}
}
Scaffoldは与えられたトップバーとボトムバーをすでに考慮しているので、ほとんどの画面はこの1つのパラメータを配線するだけでよい。落とし穴は、それを二重にやってしまうことだ。Scaffoldはそのpadding値にsafe-drawing insetsを適用するが、子コンポーネントがその上にさらに.systemBarsPadding()を呼び出すと、ステータスバーの下に2倍の隙間ができる——デザインのバグに見えるが、実際にはinsetsコードのバグだ。
insetsを手動で扱う必要がある場所
すべての画面がScaffoldを通るわけではない。Granyn、Stocky、Mintlyで手動で修正しなければならなかった3つの箇所。
- ボトムシートとダイアログ。
ModalBottomSheetは親のScaffoldのパディングの外側に自分のサーフェスを描画するので、そのコンテンツは最も内側のカラムに独自の.navigationBarsPadding()が必要だ。そうしないと最後の行がジェスチャーバーの下に埋もれる。 - キーボード。
WindowInsets.imeはnavigationBarsとは別のinsetで、キーボードの開閉に合わせてアニメーションする。画面下部に固定されたテキストフィールドには.navigationBarsPadding()ではなく.imePadding()が必要だ——キーボードが閉じているときは両者は重なるが、開いた瞬間に食い違う。 - フルブリードの画像やヘッダー。 ステータスバーの下にコンテンツを意図的に描画させたい場合——スクリーンショットギャラリーやヒーロー画像など——コンテナ全体にパディングを付けるのではなく、その上に重ねたインタラクティブなコントロール(戻るボタン、共有アイコン)に
.windowInsetsPadding(WindowInsets.safeDrawing.only(WindowInsetsSides.Top))を適用する。そうしないと狙った効果が失われる。
ユーザーに見つけられる前にこの問題の大部分を捕まえる唯一の習慣は、エミュレーターでジェスチャーナビゲーションとステータスバーの「Demo mode」カスタマイズを有効にし、ノッチのシミュレーションを有効にした状態ですべての画面をチェックすることだ。三ボタンナビゲーションとシンプルなステータスバーは、リリースしてしまうinsetsのバグのほぼすべてを隠してしまう。
Predictive back:ハードカットからプレビューへ
もう一つの変更は動作に関するもので、レイアウトの問題ではない。predictive backは、ユーザーが指を離す前に、戻るジェスチャーがどこに着地するかをシステムが示せるようにする——下にある画面が縮小していくプレビューだ——これによりユーザーは行き先を見てジェスチャーの途中で中止できる。まだオプトインしていないアプリは、依然として単純で瞬間的な画面切り替えになる。ジェスチャー自体は動くが、端末上の他のpredictive back対応アプリと並ぶとジャンプカットのように見える。
オプトインするにはマニフェストのフラグとComposeのコールバックが必要だ。
<!-- AndroidManifest.xml -->
<application android:enableOnBackInvokedCallback="true">
PredictiveBackHandler(enabled = showDetail) { progress ->
try {
progress.collect { backEvent ->
// backEvent.progress: 0f (開始) → 1f (確定)
scale = 1f - (backEvent.progress * 0.1f)
}
showDetail = false // ジェスチャー確定
} catch (e: CancellationException) {
scale = 1f // ジェスチャー中止 — 元に戻す
}
}
PredictiveBackHandler(androidx.activity.composeから)は、単一のコールバックではなく進捗イベントのFlowを渡してくれる。これがBackHandlerから来た人がつまずくポイントだ。ジェスチャーの間ずっとそれをcollectし、backEvent.progressに応じてアニメーションを駆動する。中止されたスワイプでのCancellationExceptionはエラーではなく通常の終了経路だ——これはユーザーが確定する前に指を離したことをシステムが伝える方法だ。私はこれをまさにMintlyのセッション詳細画面で使った。タイマー表示は今、戻るスワイプに合わせてわずかに縮小し、背後のリストを見せる。早めに指を離した場合は、ビューが単純に消えるのではなく、きれいに元のサイズに戻る。
リリース前に本当にチェックすべきこと
- ジェスチャーナビゲーションが有効で、三ボタンナビゲーションが無効な状態で、すべての画面が正しく描画される——ほとんどの新しい端末が出荷される状態だ。
- ステータスバーの下に二重にパディングされた隙間がない(上述の
Scaffold+手動の.systemBarsPadding()の罠)。 - ハードウェアのナビゲーションボタンがない端末で、ボトムシートとスナックバーがジェスチャーバーを避けている。
- 画面下部に近いテキストフィールドが
.imePadding()を使っており、キーボードが開いたときにジャンプしない。 - 実際のナビゲーションを持つ少なくとも1つの画面(最初にテストする画面だけでなく)にpredictive backが配線されており、画面ごとにジェスチャーの一貫性がないと感じられないようになっている。
一度これにぶつかってしまえば、どれも難しいことではない。ただ、三ボタンナビゲーションの標準的なエミュレーターでは見えない——そしてそれこそが、私たちの多くがデフォルトのまま放置している設定であり、それゆえに本来より頻繁に壊れた状態でリリースされてしまう理由でもある。
// 関連記事
ジャーナルの他の記事
Android の In-App Review API:うっとうしくならずに評価を頼む方法
Google の In-App Review API の実践ガイド。実際の仕組み、表示すべきタイミング、そしてありがちな『評価してください』ポップアップが Play ストアの評価を静かに損なっている理由。
Androidのアプリショートカットとクイック設定タイル:アプリを開かずに水分補給を記録する
AndroidのダイナミックShortcutManager APIとTileServiceの実践ガイド — ワンタップの操作でアプリ起動を完全にスキップする方法と、多くの実装が陥りがちな落とし穴について。
2026年のAndroidにおけるフォアグラウンドサービスタイプ: 自分の機能に本当に当てはまるものを選ぶ
Androidのフォアグラウンドサービスタイプの制限に関する実践ガイド — dataSync、mediaPlayback、specialUse、shortService — 強制終了や審査却下を避けて正しいタイプを選ぶ方法。