Build adaptive apps on Large Screens with Jetpack Compose
Ho Chi Minh City 2024
Luu Ngoc Lan
@Mobile Engineer - Kromlab
What’s needed?
Laptop(Windows/Mac/Linux)
Android Studio Koala or latest
JDK >= 11, Gradle >8.5, Kotlin >1.8
GitHub account
Source code: https://github.com/LuuNgocLan/JetSpotify.git
⇒ Clone repo LuuNgocLan/JetSpotify
⇒ Checkout branch feat/dev-fest-starter
Slide
Imagine your app on
Large Screens
What contents?
What is adaptive on large devices
Analyzing adaptive layout on Spotify
Coding time
More adaptive composable
What is adaptive on large devices?
Foldable devices
https://developer.android.com/large-screens/gallery
“More space
More contents”
New decision layout
Considerations
Configuration and continuity
Multi-window and multi-resume
Camera preview and media projection
Keyboard, mouse, and trackpad
What is adaptive on large devices?
Spotify adaptive app
SPOTIFY
Responsive Navigation
Responsive content UI
Responsive Content Destination
SPOTIFY
What is adaptive on large devices?
Spotify adaptive app
Coding time
Output
Home Screen
Search
Library
Premium
NavHost
Bottom Navigation
NavHostController
Starter Project
Home Screen
Search
Library
Premium
NavHost
Bottom Navigation
NavHostController
Data
Output
Step by step
Use WindowSizeClasses
dependencies {
...
implementation(platform("androidx.compose:compose-bom:2024.09.03"))
implementation("androidx.activity:activity-compose:1.9.0")
implementation("androidx.compose.material:material-icons-extended")
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.material3:material3-window-size-class")
implementation("androidx.compose.ui:ui")
...
}
build.gradle.kts
Decision layout
Navigation drawer
Navigation Rail
Navigation Bottom
PermanentNavigationDrawer(
drawerContent = {
PermanentDrawerSheet(Modifier.width(dimensionResource(R.dimen.drawer_width))) {
JetSpotifyDrawerContent(
selectedDestination = currentRoute?.let {
JetSpotifyTab.values().first { e -> e.name == it }
} ?: JetSpotifyTab.Home,
onTabPressed = { jetSpotifyTab ->
onTabPressed(jetSpotifyTab)
},
navItems = navigationItemContentList,
modifier = Modifier
.wrapContentWidth()
.fillMaxHeight()
.background(MaterialTheme.colorScheme.inverseOnSurface)
.padding(top = dimensionResource(R.dimen.drawer_padding_header))
.testTag(navigationDrawerContentDescription)
)
}
},
) {
/* Main Navigation Host*/
}
JetSpotifyMainScreen.kt
PermanentNavigationDrawer(
drawerContent = {
PermanentDrawerSheet(Modifier.width(dimensionResource(R.dimen.drawer_width))) {
JetSpotifyDrawerContent(
selectedDestination = currentRoute?.let {
JetSpotifyTab.values().first { e -> e.name == it }
} ?: JetSpotifyTab.Home,
onTabPressed = { jetSpotifyTab ->
onTabPressed(jetSpotifyTab)
},
navItems = navigationItemContentList,
modifier = Modifier
.wrapContentWidth()
.fillMaxHeight()
.background(MaterialTheme.colorScheme.inverseOnSurface)
.padding(top = dimensionResource(R.dimen.drawer_padding_header))
.testTag(navigationDrawerContentDescription)
)
}
},
) {
/* Main Navigation Host*/
}
JetSpotifyMainScreen.kt
Or can use NavigationSuiteScaffold
What is adaptive on large devices?
Spotify adaptive app
Coding time
More adaptive composable
ListDetailPaneScaffold
SupportingPaneScaffold
Key takeaways
References
Thank you!
Luu Ngoc Lan
@Mobile Engineer - Kromlab