Skip to content

Commit

Permalink
Use M3 adaptive navigation (#317)
Browse files Browse the repository at this point in the history
  • Loading branch information
fornewid authored Dec 29, 2024
1 parent 148b2a2 commit e6d3b59
Show file tree
Hide file tree
Showing 10 changed files with 35 additions and 177 deletions.
1 change: 0 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ dependencies {
implementation libs.androidx.hilt.navigation.compose
implementation libs.compose.foundation
implementation libs.compose.material3
implementation libs.compose.material3.windowsizeclass
implementation libs.compose.ui

implementation libs.androidx.profileinstaller
Expand Down
6 changes: 4 additions & 2 deletions app/dependencies/releaseRuntimeClasspath.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ androidx.compose.foundation:foundation-android:1.7.6
androidx.compose.foundation:foundation-layout-android:1.7.6
androidx.compose.foundation:foundation-layout:1.7.6
androidx.compose.foundation:foundation:1.7.6
androidx.compose.material3.adaptive:adaptive-android:1.0.0
androidx.compose.material3.adaptive:adaptive:1.0.0
androidx.compose.material3:material3-adaptive-navigation-suite-android:1.3.1
androidx.compose.material3:material3-adaptive-navigation-suite:1.3.1
androidx.compose.material3:material3-android:1.3.1
androidx.compose.material3:material3-window-size-class-android:1.3.1
androidx.compose.material3:material3-window-size-class:1.3.1
androidx.compose.material3:material3:1.3.1
androidx.compose.material:material-android:1.7.6
androidx.compose.material:material-icons-core-android:1.7.6
Expand Down
7 changes: 1 addition & 6 deletions app/src/main/java/soup/movie/ui/main/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.core.view.WindowCompat
import dagger.hilt.android.AndroidEntryPoint
import soup.movie.R
Expand All @@ -31,16 +29,13 @@ class MainActivity : AppCompatActivity() {

private val viewModel: MainViewModel by viewModels()

@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.Theme_Moop)
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
MovieTheme {
MainNavGraph(
widthSizeClass = calculateWindowSizeClass(this).widthSizeClass,
)
MainNavGraph()
}
}

Expand Down
6 changes: 1 addition & 5 deletions app/src/main/java/soup/movie/ui/main/MainNavGraph.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package soup.movie.ui.main

import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
Expand Down Expand Up @@ -43,9 +42,7 @@ private sealed interface Screen {
}

@Composable
fun MainNavGraph(
widthSizeClass: WindowWidthSizeClass,
) {
fun MainNavGraph() {
val navController = rememberNavController()
NavHost(
navController,
Expand All @@ -54,7 +51,6 @@ fun MainNavGraph(
composable<Screen.Main> {
val factory = rememberHomeComposableFactory()
factory.HomeNavGraph(
widthSizeClass = widthSizeClass,
onSearchClick = {
navController.navigate(Screen.Search)
},
Expand Down
1 change: 0 additions & 1 deletion feature/home/api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@ dependencies {
implementation libs.kotlin.stdlib

implementation libs.compose.foundation
implementation libs.compose.material3.windowsizeclass
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package soup.movie.feature.home

import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
Expand All @@ -30,7 +29,6 @@ interface HomeComposableFactory {

@Composable
fun HomeNavGraph(
widthSizeClass: WindowWidthSizeClass,
onSearchClick: () -> Unit,
onSettingsClick: () -> Unit,
onMovieItemClick: (MovieModel) -> Unit,
Expand Down
2 changes: 1 addition & 1 deletion feature/home/impl/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ dependencies {
implementation libs.compose.animation.graphics
implementation libs.compose.foundation
implementation libs.compose.material3
implementation libs.compose.material3.windowsizeclass
implementation libs.compose.material3.adaptivenavigation
implementation libs.compose.ui

testImplementation projects.testing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package soup.movie.feature.home.impl

import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.hilt.navigation.compose.hiltViewModel
Expand All @@ -27,13 +26,11 @@ class HomeComposableFactoryImpl @Inject constructor() : HomeComposableFactory {

@Composable
override fun HomeNavGraph(
widthSizeClass: WindowWidthSizeClass,
onSearchClick: () -> Unit,
onSettingsClick: () -> Unit,
onMovieItemClick: (MovieModel) -> Unit,
) {
HomeNavGraph(
widthSizeClass = widthSizeClass,
viewModel = hiltViewModel(),
onSearchClick = onSearchClick,
onSettingsClick = onSettingsClick,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,15 @@ import androidx.compose.animation.graphics.res.animatedVectorResource
import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
import androidx.compose.animation.graphics.vector.AnimatedImageVector
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationBarItemDefaults
import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.NavigationRailItemDefaults
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.VerticalDivider
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import soup.movie.core.designsystem.icon.MovieIcons
import soup.movie.core.designsystem.showToast
Expand All @@ -52,24 +38,20 @@ import soup.movie.resources.R

@Composable
fun HomeNavGraph(
widthSizeClass: WindowWidthSizeClass,
viewModel: HomeViewModel,
onSearchClick: () -> Unit,
onSettingsClick: () -> Unit,
onMovieItemClick: (MovieModel) -> Unit,
) {
val currentMainTab by viewModel.selectedMainTab.collectAsState()
val tabs = MainTabUiModel.values()
MainScaffold(
widthSizeClass = widthSizeClass,
HomeScaffold(
currentTab = currentMainTab,
tabs = tabs,
tabs = MainTabUiModel.entries.toTypedArray(),
onTabSelected = { mainTab ->
viewModel.onMainTabSelected(mainTab)
},
modifier = Modifier.systemBarsPadding(),
) { paddingValues ->
Box(modifier = Modifier.padding(paddingValues)) {
) {
Box {
when (currentMainTab) {
MainTabUiModel.Home -> {
HomeScreen(
Expand All @@ -94,144 +76,35 @@ fun HomeNavGraph(
}
}

@Composable
private fun MainScaffold(
widthSizeClass: WindowWidthSizeClass,
currentTab: MainTabUiModel,
tabs: Array<MainTabUiModel>,
onTabSelected: (MainTabUiModel) -> Unit,
modifier: Modifier = Modifier,
onTabReselected: (MainTabUiModel) -> Unit = onTabSelected,
content: @Composable (PaddingValues) -> Unit,
) {
when (widthSizeClass) {
WindowWidthSizeClass.Compact -> {
CompactScreen(
currentTab = currentTab,
tabs = tabs,
onTabSelected = onTabSelected,
onTabReselected = onTabReselected,
modifier = modifier,
content = content,
)
}
WindowWidthSizeClass.Medium,
WindowWidthSizeClass.Expanded,
-> {
MediumScreen(
currentTab = currentTab,
tabs = tabs,
onTabSelected = onTabSelected,
onTabReselected = onTabReselected,
modifier = modifier,
content = content,
)
}
}
}

@OptIn(ExperimentalAnimationGraphicsApi::class)
@Composable
private fun CompactScreen(
private fun HomeScaffold(
currentTab: MainTabUiModel,
tabs: Array<MainTabUiModel>,
onTabSelected: (MainTabUiModel) -> Unit,
modifier: Modifier = Modifier,
onTabReselected: (MainTabUiModel) -> Unit = onTabSelected,
content: @Composable (PaddingValues) -> Unit,
content: @Composable () -> Unit,
) {
Scaffold(
modifier = modifier,
bottomBar = {
NavigationBar {
tabs.forEach { tab ->
val selected = currentTab == tab
NavigationBarItem(
icon = {
when (tab) {
MainTabUiModel.Home -> {
Icon(
rememberAnimatedVectorPainter(
AnimatedImageVector.animatedVectorResource(MovieIcons.AvdHomeNowSelected),
selected,
),
contentDescription = null,
)
}
MainTabUiModel.Favorite -> {
Icon(
rememberAnimatedVectorPainter(
AnimatedImageVector.animatedVectorResource(MovieIcons.AvdFavoriteSelected),
selected,
),
contentDescription = null,
)
}
}
},
label = {
Text(
text = when (tab) {
MainTabUiModel.Home -> stringResource(R.string.menu_home)
MainTabUiModel.Favorite -> stringResource(R.string.menu_favorite)
},
)
},
selected = selected,
onClick = {
if (selected) {
onTabReselected(tab)
} else {
onTabSelected(tab)
}
},
colors = NavigationBarItemDefaults.colors(),
)
}
}
},
content = content,
)
}

@OptIn(ExperimentalAnimationGraphicsApi::class)
@Composable
private fun MediumScreen(
currentTab: MainTabUiModel,
tabs: Array<MainTabUiModel>,
onTabSelected: (MainTabUiModel) -> Unit,
modifier: Modifier = Modifier,
onTabReselected: (MainTabUiModel) -> Unit = onTabSelected,
content: @Composable (PaddingValues) -> Unit,
) {
Row(
modifier = modifier.fillMaxSize(),
) {
NavigationRail {
NavigationSuiteScaffold(
navigationSuiteItems = {
tabs.forEach { tab ->
val selected = currentTab == tab
NavigationRailItem(
item(
icon = {
when (tab) {
MainTabUiModel.Home -> {
Icon(
rememberAnimatedVectorPainter(
AnimatedImageVector.animatedVectorResource(MovieIcons.AvdHomeNowSelected),
selected,
),
contentDescription = null,
)
}
MainTabUiModel.Favorite -> {
Icon(
rememberAnimatedVectorPainter(
AnimatedImageVector.animatedVectorResource(MovieIcons.AvdFavoriteSelected),
selected,
),
contentDescription = null,
)
}
}
Icon(
rememberAnimatedVectorPainter(
animatedImageVector = when (tab) {
MainTabUiModel.Home ->
AnimatedImageVector.animatedVectorResource(MovieIcons.AvdHomeNowSelected)

MainTabUiModel.Favorite ->
AnimatedImageVector.animatedVectorResource(MovieIcons.AvdFavoriteSelected)
},
atEnd = selected,
),
contentDescription = null,
)
},
label = {
Text(
Expand All @@ -249,11 +122,10 @@ private fun MediumScreen(
onTabSelected(tab)
}
},
colors = NavigationRailItemDefaults.colors(),
)
}
}
VerticalDivider(thickness = 1.dp)
content(PaddingValues())
}
},
modifier = modifier,
content = content,
)
}
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ compose-bom = { module = "androidx.compose:compose-bom", version.ref = "compose-
compose-foundation = { module = "androidx.compose.foundation:foundation" }
compose-materialIconsExtended = { module = "androidx.compose.material:material-icons-extended" }
compose-material3 = { module = "androidx.compose.material3:material3" }
compose-material3-windowsizeclass = { module = "androidx.compose.material3:material3-window-size-class" }
compose-material3-adaptivenavigation = { module = "androidx.compose.material3:material3-adaptive-navigation-suite" }
compose-ui = { module = "androidx.compose.ui:ui" }
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
Expand Down

0 comments on commit e6d3b59

Please sign in to comment.