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
Jetpack Composeで 様々な画面サイズに対応する/With Jetpack Com...
Search
t_takahiro
January 23, 2024
Programming
0
1.6k
Jetpack Composeで 様々な画面サイズに対応する/With Jetpack Compose Adapt to various screen sizes
2024/1/23開催 ZOZO Tech Meetup Androidの発表資料です。
t_takahiro
January 23, 2024
Tweet
Share
Other Decks in Programming
See All in Programming
Startups on Rails in Past, Present and Future–Irina Nazarova, RailsConf 2025
irinanazarova
0
250
「テストは愚直&&網羅的に書くほどよい」という誤解 / Test Smarter, Not Harder
munetoshi
0
200
TypeScriptでDXを上げろ! Hono編
yusukebe
3
770
Claude Code派?Gemini CLI派? みんなで比較LT会!_20250716
junholee
1
530
「App Intent」よくわからんけどすごい!
rinngo0302
1
100
Deep Dive into ~/.claude/projects
hiragram
14
14k
AIと”コードの評価関数”を共有する / Share the "code evaluation function" with AI
euglena1215
1
180
はじめてのWeb API体験 ー 飲食店検索アプリを作ろうー
akinko_0915
0
140
脱Riverpod?fqueryで考える、TanStack Queryライクなアーキテクチャの可能性
ostk0069
0
500
GPUを計算資源として使おう!
primenumber
1
250
Agentic Coding: The Future of Software Development with Agents
mitsuhiko
0
130
PipeCDのプラグイン化で目指すところ
warashi
1
300
Featured
See All Featured
How GitHub (no longer) Works
holman
314
140k
The Cost Of JavaScript in 2023
addyosmani
51
8.6k
The Language of Interfaces
destraynor
158
25k
BBQ
matthewcrist
89
9.7k
Agile that works and the tools we love
rasmusluckow
329
21k
Code Review Best Practice
trishagee
69
19k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
How STYLIGHT went responsive
nonsquared
100
5.6k
How to Think Like a Performance Engineer
csswizardry
25
1.7k
Music & Morning Musume
bryan
46
6.7k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
44
2.4k
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
Transcript
Jetpack Composeで 様々な画面サイズに対応する 株式会社ZOZO ブランドソリューション開発本部 FAANS部 フロントエンドブロック 田中 崇裕
Copyright © ZOZO, Inc. 1
© ZOZO, Inc. 株式会社ZOZO ブランドソリューション開発本部 FAANS部 フロントエンドブロック 田中 崇裕 •
2023年10月中途入社 • 3年日記をもう少しで書き終えます 2
© ZOZO, Inc. 3 目次 1. 様々な画面サイズに対応することについて 2. WindowSizeClassを用いた実装 3.
その他の手法 4. まとめ
© ZOZO, Inc. 4 1 様々な画面サイズに対応することについて 実情 • なかなか優先度が高くない •
色々な形や大きさの端末があって気にしていたらキリがない
© ZOZO, Inc. 5 1 様々な画面サイズに対応することについて 実情 • なかなか優先度が高くない •
色々な形や大きさの端末があって気にしていたらキリがない しかし • Androidプラットフォームは様々な端末にアプローチしやすい • 市場にモバイル以外の端末が増えてきている
© ZOZO, Inc. 6 1 様々な画面サイズに対応することについて 実情 • なかなか優先度が高くない •
色々な形や大きさの端末があって気にしていたらキリがない しかし • Androidプラットフォームは様々な端末にアプローチしやすい • 市場にモバイル以外の端末が増えてきている 対応することについて • UX向上に少なからず繋がるはず • いま対応するかはさておき、いずれ対応が必要になった時に心理的ハードルが低く なっていることが大事
© ZOZO, Inc. 7 2 WindowSizeClassを用いた実装 2-1 対応する画面サイズの定義 2-2 事前準備
2-3 実装例 (ナビゲーション、ペイン)
© ZOZO, Inc. 8 2-1 対応する画面サイズの定義 マテリアルデザインで分類されている3つのサイズに対して対応する (heightにも同じ定義があるが今回はwidthを使用) https://codelabs.developers.google.com/jetpack-compose-adaptability?hl=en#2
© ZOZO, Inc. 9 2-1 対応する画面サイズの定義 マテリアルデザインで分類されている3つのサイズに対して対応する (heightにも同じ定義があるが今回はwidthを使用) →WindowSizeClassを用いれば簡単に分岐が可能 https://codelabs.developers.google.com/jetpack-compose-adaptability?hl=en#2
© ZOZO, Inc. 10 2-2 事前準備 依存関係を追加 dependencies { implementation
"androidx.compose.material3:material3-window-size-class:1.1.0" }
© ZOZO, Inc. 11 2-2 事前準備 端末の横幅を取得する @OptIn(ExperimentalMaterial3WindowSizeClassApi::class) override fun
onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ReplyTheme { val windowSize = calculateWindowSizeClass(this) ReplyApp(windowSize.widthSizeClass) } } }
© ZOZO, Inc. 12 2-2 事前準備(補足) @Previewで別々の端末サイズを指定可能 @Preview(showBackground = true,
widthDp = 700) @Composable fun ReplyAppPreviewTablet() { ReplyTheme { ReplyApp( replyHomeUIState = ReplyHomeUIState(,,,), windowSize = WindowWidthSizeClass.Medium ) } }
© ZOZO, Inc. 13 2-2 事前準備(補足) AndroidStudio>Tools>DeviceManager>CreateDvices>Resizable(Experimental)をAPI33で作成
© ZOZO, Inc. 14 2-3 実装例 端末サイズによって以下の出し分けを実施する • ナビゲーション •
ペイン
© ZOZO, Inc. 15 2-3 実装例(ナビゲーション) ナビゲーションの種類 • Bottom Navigation
• Navigation Rail • NavigationDrawer ◦ Modal Navigation Drawer ◦ Permanent Navigation Drawer
© ZOZO, Inc. 16 2-3 実装例(ナビゲーション) ナビゲーションの種類 • Bottom Navigation
• Navigation Rail • NavigationDrawer ◦ Modal Navigation Drawer ◦ Permanent Navigation Drawer
© ZOZO, Inc. 17 2-3 実装例(ナビゲーション) ナビゲーションの種類 • Bottom Navigation
• Navigation Rail • NavigationDrawer ◦ Modal Navigation Drawer ◦ Permanent Navigation Drawer
© ZOZO, Inc. 18 2-3 実装例(ナビゲーション) ナビゲーションの種類 • Bottom Navigation
• Navigation Rail • NavigationDrawer ◦ Modal Navigation Drawer ◦ Permanent Navigation Drawer enum class ReplyNavigationType { BOTTOM_NAVIGATION, NAVIGATION_RAIL, PERMANENT_NAVIGATION_DRAWER }
© ZOZO, Inc. 19 2-3 実装例(ナビゲーション) @Composable fun ReplyApp( windowSize:
WindowWidthSizeClass, ) { val navigationType = when (windowSize) { WindowWidthSizeClass.Compact -> ReplyNavigationType.BOTTOM_NAVIGATION WindowWidthSizeClass.Medium -> ReplyNavigationType.NAVIGATION_RAIL WindowWidthSizeClass.Expanded -> ReplyNavigationType.PERMANENT_NAVIGATION_DRAWER else -> ReplyNavigationType.BOTTOM_NAVIGATION } ReplyNavigationWrapperUI(navigationType) }
© ZOZO, Inc. 20 2-3 実装例(ナビゲーション) @Composable private fun ReplyNavigationWrapperUI(
navigationType: ReplyNavigationType, ) { if (navigationType == ReplyNavigationType.PERMANENT_NAVIGATION_DRAWER) { PermanentNavigationDrawer( drawerContent = { PermanentDrawerSheet { NavigationDrawerContent() //これは自分で作成 } } ) { ReplyAppContent(navigationType) //さらに子に渡す } }
© ZOZO, Inc. 21 2-3 実装例(ナビゲーション) } else { ModalNavigationDrawer(
drawerContent = { ModalDrawerSheet { NavigationDrawerContent() //これは自分で作成 } }, ) { ReplyAppContent(navigationType) //さらに子に渡す } }
© ZOZO, Inc. 22 2-3 実装例(ナビゲーション) @Composable fun ReplyAppContent( navigationType:
ReplyNavigationType, ) { Row(,,,) { AnimatedVisibility(visible = navigationType == ReplyNavigationType.NAVIGATION_RAIL) { ReplyNavigationRail() //これは自分で作成 } Column(,,,) { ReplyListOnlyContent() AnimatedVisibility(visible = navigationType == ReplyNavigationType.BOTTOM_NAVIGATION) { ReplyBottomNavigationBar() //これは自分で作成 } } } }
© ZOZO, Inc. 23 2-3 実装例(ペイン) ペインとは → 区画のこと 1つ 2つ
© ZOZO, Inc. enum class ReplyContentType { LIST_ONLY, LIST_AND_DETAIL }
24 2-3 実装例(ペイン) ペインとは → 区画のこと LIST_ONLY LIST_AND_DETAIL
© ZOZO, Inc. 25 2-3 実装例(ペイン) @Composable fun ReplyApp( windowSize:
WindowWidthSizeClass, ) { val contentType = when (windowSize) { WindowWidthSizeClass.Compact -> ReplyContentType.LIST_ONLY WindowWidthSizeClass.Medium -> ReplyContentType.LIST_ONLY WindowWidthSizeClass.Expanded -> ReplyContentType.LIST_AND_DETAIL else -> ReplyContentType.LIST_ONLY } ReplyNavigationWrapperUI(contentType) // ReplyContent()に渡すのみ }
© ZOZO, Inc. 26 2-3 実装例(ペイン) @Composable fun ReplyAppContent( contentType:
ReplyContentType, ) { Row(,,,) { Column(,,,) { if (contentType == ReplyContentType.LIST_AND_DETAIL) { ReplyListAndDetailContent() //これは自分で作成 } else { ReplyListOnlyContent() //これは自分で作成 } } } }
© ZOZO, Inc. 27 3 その他の手法 3-1 ListDetailPaneScaffold 3-2 NavigationSuiteScaffold
※どちらもalpha版 https://medium.com/androiddevelopers/new-apis-for-adaptive-layouts-in-jetpack-compose-f27cace48bcd
© ZOZO, Inc. 28 3-1 ListDetailPaneScaffold ListDetailPaneScaffold( ,,, listPane =
{ MyList(,,,) }, detailPane = { MyDetails(,,,) }, ) https://medium.com/androiddevelopers/new-apis-for-adaptive-layouts-in-jetpack-compose-f27cace48bcd implementation "androidx.compose.material3:material3-adaptive-android:1.0.0-alpha01"
© ZOZO, Inc. 29 3-2 NavigationSuiteScaffold NavigationSuiteScaffold( navigationSuiteItems = {
navItems.forEachIndexed {,,, -> item( icon = {,,,}, label = {,,,}, selected = ,,,, onClick = {,,,} ) } } ) { // Screen content. Text(,,,) } https://medium.com/androiddevelopers/new-apis-for-adaptive-layouts-in-jetpack-compose-f27cace48bcd implementation "androidx.compose.material3:material3-adaptive-navigation-suite-android:1.0.0-alpha01"
© ZOZO, Inc. 30 4 まとめ • 様々な画面サイズに対応する場合、対応する形を最初に決める • 画面サイズ対応する際はWindowSizeClassのコールバックを活用する
• 取得したサイズごとにナビゲーションやペインを出し分けることで対応 • 今後、より実装しやすくなることに期待
None