Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Jetpack Composeで 様々な画面サイズに対応する/With Jetpack Compose Adapt to various screen sizes

t_takahiro
January 23, 2024

Jetpack Composeで 様々な画面サイズに対応する/With Jetpack Compose Adapt to various screen sizes

2024/1/23開催 ZOZO Tech Meetup Androidの発表資料です。

t_takahiro

January 23, 2024
Tweet

Transcript

  1. © ZOZO, Inc. 5 1 様々な画面サイズに対応することについて 実情 • なかなか優先度が高くない •

    色々な形や大きさの端末があって気にしていたらキリがない しかし • Androidプラットフォームは様々な端末にアプローチしやすい • 市場にモバイル以外の端末が増えてきている
  2. © ZOZO, Inc. 6 1 様々な画面サイズに対応することについて 実情 • なかなか優先度が高くない •

    色々な形や大きさの端末があって気にしていたらキリがない しかし • Androidプラットフォームは様々な端末にアプローチしやすい • 市場にモバイル以外の端末が増えてきている 対応することについて • UX向上に少なからず繋がるはず • いま対応するかはさておき、いずれ対応が必要になった時に心理的ハードルが低く なっていることが大事
  3. © ZOZO, Inc. 10 2-2 事前準備 依存関係を追加 dependencies { implementation

    "androidx.compose.material3:material3-window-size-class:1.1.0" }
  4. © 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) } } }
  5. © ZOZO, Inc. 12 2-2 事前準備(補足) @Previewで別々の端末サイズを指定可能 @Preview(showBackground = true,

    widthDp = 700) @Composable fun ReplyAppPreviewTablet() { ReplyTheme { ReplyApp( replyHomeUIState = ReplyHomeUIState(,,,), windowSize = WindowWidthSizeClass.Medium ) } }
  6. © ZOZO, Inc. 15 2-3 実装例(ナビゲーション) ナビゲーションの種類 • Bottom Navigation

    • Navigation Rail • NavigationDrawer ◦ Modal Navigation Drawer ◦ Permanent Navigation Drawer
  7. © ZOZO, Inc. 16 2-3 実装例(ナビゲーション) ナビゲーションの種類 • Bottom Navigation

    • Navigation Rail • NavigationDrawer ◦ Modal Navigation Drawer ◦ Permanent Navigation Drawer
  8. © ZOZO, Inc. 17 2-3 実装例(ナビゲーション) ナビゲーションの種類 • Bottom Navigation

    • Navigation Rail • NavigationDrawer ◦ Modal Navigation Drawer ◦ Permanent Navigation Drawer
  9. © 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 }
  10. © 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) }
  11. © ZOZO, Inc. 20 2-3 実装例(ナビゲーション) @Composable private fun ReplyNavigationWrapperUI(

    navigationType: ReplyNavigationType, ) { if (navigationType == ReplyNavigationType.PERMANENT_NAVIGATION_DRAWER) { PermanentNavigationDrawer( drawerContent = { PermanentDrawerSheet { NavigationDrawerContent() //これは自分で作成 } } ) { ReplyAppContent(navigationType) //さらに子に渡す } }
  12. © ZOZO, Inc. 21 2-3 実装例(ナビゲーション) } else { ModalNavigationDrawer(

    drawerContent = { ModalDrawerSheet { NavigationDrawerContent() //これは自分で作成 } }, ) { ReplyAppContent(navigationType) //さらに子に渡す } }
  13. © 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() //これは自分で作成 } } } }
  14. © ZOZO, Inc. enum class ReplyContentType { LIST_ONLY, LIST_AND_DETAIL }

    24 2-3 実装例(ペイン) ペインとは → 区画のこと LIST_ONLY LIST_AND_DETAIL
  15. © 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()に渡すのみ }
  16. © ZOZO, Inc. 26 2-3 実装例(ペイン) @Composable fun ReplyAppContent( contentType:

    ReplyContentType, ) { Row(,,,) { Column(,,,) { if (contentType == ReplyContentType.LIST_AND_DETAIL) { ReplyListAndDetailContent() //これは自分で作成 } else { ReplyListOnlyContent() //これは自分で作成 } } } }
  17. © ZOZO, Inc. 27 3 その他の手法 3-1 ListDetailPaneScaffold 3-2 NavigationSuiteScaffold

    ※どちらもalpha版 https://medium.com/androiddevelopers/new-apis-for-adaptive-layouts-in-jetpack-compose-f27cace48bcd
  18. © 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"
  19. © 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"
  20. © ZOZO, Inc. 30 4 まとめ • 様々な画面サイズに対応する場合、対応する形を最初に決める • 画面サイズ対応する際はWindowSizeClassのコールバックを活用する

    • 取得したサイズごとにナビゲーションやペインを出し分けることで対応 • 今後、より実装しやすくなることに期待