Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Edge-to-Edge / WindowInsets との上手な付き合い方
Search
wcaokaze
April 24, 2025
Programming
0
85
Edge-to-Edge / WindowInsets との上手な付き合い方
https://youtu.be/j5ckxa6_2gc
wcaokaze
April 24, 2025
Tweet
Share
More Decks by wcaokaze
See All by wcaokaze
Composeのイベント地獄から脱出しよう! The Elm Architectureの導入にみる可能性
wcaokaze
0
100
Jetpack Composeで拡大縮小、斜め方向のスクロールを実装する
wcaokaze
0
560
Other Decks in Programming
See All in Programming
Giselleで作るAI QAアシスタント 〜 Pull Requestレビューに継続的QAを
codenote
0
330
クラウドに依存しないS3を使った開発術
simesaba80
0
220
脳の「省エネモード」をデバッグする ~System 1(直感)と System 2(論理)の切り替え~
panda728
PRO
0
130
Denoのセキュリティに関する仕組みの紹介 (toranoana.deno #23)
uki00a
0
220
リリース時」テストから「デイリー実行」へ!開発マネージャが取り組んだ、レガシー自動テストのモダン化戦略
goataka
0
160
令和最新版Android Studioで化石デバイス向けアプリを作る
arkw
0
470
ZJIT: The Ruby 4 JIT Compiler / Ruby Release 30th Anniversary Party
k0kubun
1
310
HTTPプロトコル正しく理解していますか? 〜かわいい猫と共に学ぼう。ฅ^•ω•^ฅ ニャ〜
hekuchan
2
610
Combinatorial Interview Problems with Backtracking Solutions - From Imperative Procedural Programming to Declarative Functional Programming - Part 2
philipschwarz
PRO
0
130
CSC307 Lecture 02
javiergs
PRO
1
760
React 19でつくる「気持ちいいUI」- 楽観的UIのすすめ
himorishige
11
4.5k
公共交通オープンデータ × モバイルUX 複雑な運行情報を 『直感』に変換する技術
tinykitten
PRO
0
180
Featured
See All Featured
My Coaching Mixtape
mlcsv
0
21
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
2
3.9k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
0
51
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
54
49k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
41
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
40
Principles of Awesome APIs and How to Build Them.
keavy
127
17k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
0
1k
How To Stay Up To Date on Web Technology
chriscoyier
791
250k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
120
Transcript
Edge-to-Edge / WindowInsetsとの 上手な付き合い方 @wcaokaze
自己紹介 • wcaokaze(わかおかぜ) • Palcy Android 2
Edge-to-Edgeとは? 3
Edge-to-Edgeとは? 画面の端から端までアプリの領域に なる 4 出典: 太宰治「走れメロス」
SDK35以降、強制される 5
SDK35以降Edge-to-Edge強制 35以降でも無効化する方法があるらしいが…? 6
SDK35以降Edge-to-Edge強制 35以降でも無効化する方法があるらしいが…? 今回は無効化しない場合の話 7
SDK35以降Edge-to-Edge強制 より厳密には? 8
SDK35以降Edge-to-Edge強制 より厳密には? 下記条件を満たすとEdge-to-Edgeが有効化される • targetSdk 35以降でビルドしたアプリ • Android 15以降で実行 9
SDK35以降Edge-to-Edge強制 ただし、これはEdge-to-Edgeが「強制される」条件。 この条件を満たさなくてもEdge-to-Edgeにすることは可能 10
SDK35以降Edge-to-Edge強制 ただし、これはEdge-to-Edgeが「強制される」条件。 この条件を満たさなくてもEdge-to-Edgeにすることは可能 どのみち対応するのであればAndroid 14以前でもEdge-to-Edgeにしたい 11
Android 14以前のEdge-to-Edge • APIレベル 26(Android 8.0)以降 ◦ フル対応可能 • APIレベル
25(Android 7.1)以前 ◦ ナビゲーションバーのアイコン色が白固定 • APIレベル 22(Android 5.1)以前 ◦ ステータスバーのアイコン色が白固定 • APIレベル 20(Android 4.4)以前 ◦ 割愛 12
Android 14以前のEdge-to-Edge • APIレベル 26(Android 8.0)以降 ◦ フル対応可能 • APIレベル
25(Android 7.1)以前 ◦ ナビゲーションバーのアイコン色が白固定 • APIレベル 22(Android 5.1)以前 ◦ ステータスバーのアイコン色が白固定 • APIレベル 20(Android 4.4)以前 ◦ 割愛 13 出典: 太宰治「走れメロス」
Android 14以前のEdge-to-Edge • APIレベル 26(Android 8.0)以降 ◦ フル対応可能 • APIレベル
25(Android 7.1)以前 ◦ ナビゲーションバーのアイコン色が白固定 • APIレベル 22(Android 5.1)以前 ◦ ステータスバーのアイコン色が白固定 • APIレベル 20(Android 4.4)以前 ◦ 割愛 14 出典: 太宰治「走れメロス」
Android 14以前のEdge-to-Edge • APIレベル 26(Android 8.0)以降 ◦ フル対応可能 • APIレベル
25(Android 7.1)以前 ◦ ナビゲーションバーのアイコン色が白固定 • APIレベル 22(Android 5.1)以前 ◦ ステータスバーのアイコン色が白固定 • APIレベル 20(Android 4.4)以前 ◦ 割愛 15 出典: 太宰治「走れメロス」
Android 14以前のEdge-to-Edge • APIレベル 26(Android 8.0)以降 ◦ フル対応可能 • APIレベル
25(Android 7.1)以前 ◦ ナビゲーションバーのアイコン色が白固定 • APIレベル 22(Android 5.1)以前 ◦ ステータスバーのアイコン色が白固定 • APIレベル 20(Android 4.4)以前 ◦ 割愛 16 出典: 太宰治「走れメロス」
Android 14以前のEdge-to-Edge • APIレベル 26(Android 8.0)以降 ◦ フル対応可能 • APIレベル
25(Android 7.1)以前 ◦ ナビゲーションバーのアイコン色が白固定 • APIレベル 22(Android 5.1)以前 ◦ ステータスバーのアイコン色が白固定 • APIレベル 20(Android 4.4)以前 ◦ 割愛 17 出典: 太宰治「走れメロス」
Android 14以前のEdge-to-Edge • APIレベル 26(Android 8.0)以降 ◦ フル対応可能 • APIレベル
25(Android 7.1)以前 ◦ ナビゲーションバーのアイコン色が白固定 • APIレベル 22(Android 5.1)以前 ◦ ステータスバーのアイコン色が白固定 • APIレベル 20(Android 4.4)以前 ◦ 割愛 18
Android 14以前のEdge-to-Edge • APIレベル 26(Android 8.0)以降 ◦ フル対応可能 • APIレベル
25(Android 7.1)以前 ◦ ナビゲーションバーのアイコン色が白固定 • APIレベル 22(Android 5.1)以前 ◦ ステータスバーのアイコン色が白固定 • APIレベル 20(Android 4.4)以前 ◦ 割愛 19 ⎫ ⎬ ⎭ 工夫が必要
Android 14以前のEdge-to-Edge • APIレベル 26(Android 8.0)以降 ◦ フル対応可能 • APIレベル
25(Android 7.1)以前 ◦ ナビゲーションバーのアイコン色が白固定 • APIレベル 22(Android 5.1)以前 ◦ ステータスバーのアイコン色が白固定 • APIレベル 20(Android 4.4)以前 ◦ 割愛 20 出典: 太宰治「走れメロス」
Android 14以前のEdge-to-Edge • APIレベル 26(Android 8.0)以降 ◦ フル対応可能 • APIレベル
25(Android 7.1)以前 ◦ ナビゲーションバーのアイコン色が白固定 • APIレベル 22(Android 5.1)以前 ◦ ステータスバーのアイコン色が白固定 • APIレベル 20(Android 4.4)以前 ◦ 割愛 21 出典: 太宰治「走れメロス」
Android 14以前のEdge-to-Edge • APIレベル 26(Android 8.0)以降 ◦ フル対応可能 • APIレベル
25(Android 7.1)以前 ◦ ナビゲーションバーのアイコン色が白固定 • APIレベル 22(Android 5.1)以前 ◦ ステータスバーのアイコン色が白固定 • APIレベル 20(Android 4.4)以前 ◦ 割愛 22 出典: 太宰治「走れメロス」
Android 14以前のEdge-to-Edge APIレベル25(Android 7.1)以前をサポート しない場合 23 出典: 太宰治「走れメロス」
Android 14以前のEdge-to-Edge APIレベル25(Android 7.1)以前をサポート しない場合 24 出典: 太宰治「走れメロス」 val windowInsetsController
= WindowCompat.getInsetsController(window, window.decorView) windowInsetsController.isAppearanceLightStatusBars = true windowInsetsController.isAppearanceLightNavigationBars = true
Edge-to-Edge対応とは? 25
Edge-to-Edge対応とは? Edge-to-Edgeを有効化してみる 26 出典: 太宰治「走れメロス」
Edge-to-Edge対応とは? Edge-to-Edgeを有効化してみる 27 出典: 太宰治「走れメロス」
Edge-to-Edge対応とは? 画面端のUIがシステムバー等とカブらないように レイアウトする 28 出典: 太宰治「走れメロス」
WindowInsets 29
WindowInsets 画面端にあるものの大きさを知ることができる 30 WindowInsets( left = 0dp, top = 56dp,
right = 0dp, bottom = 48dp )
WindowInsets WindowInsets.statusBars 31
WindowInsets WindowInsets.navigationBars 32
WindowInsets WindowInsets.displayCutout 33
WindowInsets WindowInsets.ime 34
WindowInsets WindowInsets.safeDrawing 35
WindowInsets WindowInsets.safeGestures 36
どれを使えばいい? ほぼsafeDrawing一択 37
どれを使えばいい? ほぼsafeDrawing一択 38 出典: 太宰治「走れメロス」 Text( text = "メロスは激怒した。" +
"必ず、かの邪智暴虐の王を除かなければならぬと決意した。", modifier = Modifier .align(Alignment.BottomCenter) .windowInsetsPadding(WindowInsets.navigationBars) ) ❌
どれを使えばいい? ほぼsafeDrawing一択 39 出典: 太宰治「走れメロス」 Text( text = "メロスは激怒した。" +
"必ず、かの邪智暴虐の王を除かなければならぬと決意した。", modifier = Modifier .align(Alignment.BottomCenter) .windowInsetsPadding(WindowInsets.navigationBars) ) ❌
どれを使えばいい? ほぼsafeDrawing一択 40 出典: 太宰治「走れメロス」 Text( text = "メロスは激怒した。" +
"必ず、かの邪智暴虐の王を除かなければならぬと決意した。", modifier = Modifier .align(Alignment.BottomCenter) .windowInsetsPadding(WindowInsets.navigationBars) ) ❌
どれを使えばいい? ほぼsafeDrawing一択 41 出典: 太宰治「走れメロス」 Text( text = "メロスは激怒した。" +
"必ず、かの邪智暴虐の王を除かなければならぬと決意した。", modifier = Modifier .align(Alignment.BottomCenter) .windowInsetsPadding( WindowInsets.safeDrawing.only(WindowInsetsSides.Bottom) ) ) ⭕
実践 42
実践 画面端のUIがシステムバー等とカブらないように レイアウトする 43 出典: 太宰治「走れメロス」
実践 画面上部(AppBar) 44 出典: 太宰治「走れメロス」 TopAppBar( title = { …
}, navigationIcon = { … }, actions = { … }, )
実践 画面上部(AppBar) windowInsetsを渡す 45 出典: 太宰治「走れメロス」 TopAppBar( title = {
… }, navigationIcon = { … }, actions = { … }, windowInsets = WindowInsets.safeDrawing )
実践 画面上部(AppBar) windowInsetsを渡す 46 出典: 太宰治「走れメロス」 TopAppBar( title = {
… }, navigationIcon = { … }, actions = { … }, windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top) )
実践 画面内のすべてのComposableに同様の対応を 行う 47 出典: 太宰治「走れメロス」
No 48
WindowInsetsと重なってもいい Composableもある 49
実践 画面下部(LazyColumn) 50 出典: 太宰治「走れメロス」 LazyColumn { items(...) { …
} }
実践 画面下部(LazyColumn) 51 出典: 太宰治「走れメロス」 LazyColumn( modifier = Modifier .windowInsetsPadding(
WindowInsets.safeDrawing.only(WindowInsetsSides.Bottom) ) ) { items(...) { … } } ❌
実践 LazyColumnはスクロールが可能なため、 WindowInsetsと重ねることができる 52 出典: 太宰治「走れメロス」 LazyColumn { items(...) {
… } }
実践 LazyColumnはスクロールが可能なため、 WindowInsetsと重ねることができる 53 出典: 太宰治「走れメロス」 LazyColumn { items(...) {
… } }
実践 一番下までスクロールしたときには WindowInsetsと重なってはいけない 54 出典: 太宰治「走れメロス」 LazyColumn { items(...) {
… } }
実践 一番下までスクロールしたときには WindowInsetsと重なってはいけない 55 出典: 太宰治「走れメロス」 LazyColumn( contentPadding = WindowInsets.safeDrawing
.only(WindowInsetsSides.Bottom) .asPaddingValues() ) { items(...) { … } }
実践 左右端 56 出典: 太宰治「走れメロス」
実践 AppBarは左右端も避けなければならない 57 出典: 太宰治「走れメロス」 TopAppBar( title = { …
}, navigationIcon = { … }, actions = { … }, windowInsets = WindowInsets.safeDrawing .only(WindowInsetsSides.Top) )
実践 AppBarは左右端も避けなければならない 58 出典: 太宰治「走れメロス」 TopAppBar( title = { …
}, navigationIcon = { … }, actions = { … }, windowInsets = WindowInsets.safeDrawing .only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal) )
実践 LazyColumn部分も同様に 左右のWindowInsetsを避ける 59 出典: 太宰治「走れメロス」
No 60
WindowInsetsと重なってもいい Composableもある 61
実践 区切り線 62 出典: 太宰治「走れメロス」 HorizontalDivider( modifier = Modifier .windowInsetsPadding(
WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal) ) )
実践 背景色 63 出典: 太宰治「走れメロス」 Row( modifier = Modifier .windowInsetsPadding(
WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal) ) .background(if (background) { backgroundColor } else { Color.Transparent }) .windowInsetsPadding( WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal) ) ) { … }
完成! 64 出典: 太宰治「走れメロス」
まとめ 65
まとめ • (Jetpack Composeが動作する)すべての機種でEdge-to-Edgeを利用できる ◦ Android 7.1以前は工夫が必要 • Edge-to-Edgeに対応するためにはComposableがWindowInsetsと 重ならないようにレイアウトしなければならない
• WindowInsetsと重なってはいけないComposable ◦ ユーザーが見ているコンテンツ(画像、文字など) ◦ ユーザーが操作するもの(ボタンなど) • WindowInsetsと重なってもいいComposable ◦ スクロール可能なもの ◦ 部分的に隠れても機能が失われないもの(区切り線、背景色など) 66
Q. 大変じゃないですか? A. そうですね・・・ 67
Q. 大変じゃないですか? A. そうですね・・・ Android Studioのプレビュー機能を活用して かなり軽減できるので見てみてください https://inside.pixiv.blog/2025/03/26/163000 68
ありがとうございました 69