Skip to content

Commit

Permalink
Add adaptive navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
atomgomba committed May 24, 2024
1 parent 9a97629 commit 97aca65
Show file tree
Hide file tree
Showing 8 changed files with 32 additions and 48 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ dependencies {

implementation(libs.androidx.activity.compose)
implementation(libs.androidx.compose.material3.windowSizeClass)
implementation(libs.androidx.compose.material3.adaptiveNavigationSuite)
implementation(libs.androidx.navigation.compose)

implementation(libs.hurokBase)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.navigation.navArgument
import com.ekezet.othello.core.data.ExcludeFromCoverage
import com.ekezet.othello.core.data.models.Disk
import com.ekezet.othello.core.data.models.valueOf
import com.ekezet.othello.core.ui.R
import com.ekezet.othello.core.ui.navigation.Route

@ExcludeFromCoverage
Expand All @@ -28,12 +29,14 @@ sealed class MainRoutes : Route() {
data object GameBoardRoute : MainRoutes() {
override val id: String = "game-board"
override val icon: ImageVector = Icons.Default.PlayArrow
override val labelRes: Int = R.string.main__nav__game_board
}

@ExcludeFromCoverage
data object GameSettingsRoute : MainRoutes() {
override val id: String = "game-settings"
override val icon: ImageVector = Icons.Default.Settings
override val labelRes: Int = R.string.main__nav__game_settings

private const val PickStrategy = "pickStrategy"

Expand All @@ -53,7 +56,7 @@ sealed class MainRoutes : Route() {
"$id?$PickStrategy=${params["disk"]}"

fun make(pickStrategyFor: Disk): String =
make(mapOf(PickStrategy to pickStrategyFor.toString()))
make(mapOf("disk" to pickStrategyFor.toString()))

fun findPickStrategy(entry: NavBackStackEntry): Disk? =
Disk.valueOf(
Expand Down
5 changes: 1 addition & 4 deletions app/src/main/java/com/ekezet/othello/main/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.compose.ui.Modifier
import com.ekezet.othello.core.ui.theme.OthelloTheme

Expand All @@ -22,9 +21,7 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background,
) {
MainView(
windowSizeClass = calculateWindowSizeClass(activity = this@MainActivity),
)
MainView()
}
}
}
Expand Down
31 changes: 4 additions & 27 deletions app/src/main/java/com/ekezet/othello/main/ui/MainView.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
package com.ekezet.othello.main.ui

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.NavigationRail
import androidx.compose.material3.Scaffold
import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.collectAsState
Expand All @@ -19,7 +13,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
import androidx.navigation.NavHostController
import androidx.navigation.NavOptions
Expand All @@ -40,14 +33,13 @@ import com.ekezet.othello.main.navigation.MainRoutes.GameBoardRoute
import com.ekezet.othello.main.navigation.MainRoutes.GameSettingsRoute
import com.ekezet.othello.main.navigation.stripRoute
import com.ekezet.othello.main.ui.components.MainTopAppBar
import com.ekezet.othello.main.ui.components.NavigationActions
import com.ekezet.othello.main.ui.components.navigationActions
import kotlinx.coroutines.CoroutineScope
import org.koin.compose.koinInject

@OptIn(ExperimentalLayoutApi::class)
@Composable
internal fun MainView(
windowSizeClass: WindowSizeClass,
parentScope: CoroutineScope = rememberCoroutineScope(),
) {
val gameSettingsStore: GameSettingsStore = koinInject()
Expand All @@ -60,7 +52,6 @@ internal fun MainView(
) {
MainViewImpl(
gameSettings = gameSettings,
windowSizeClass = windowSizeClass,
)
}
}
Expand All @@ -69,7 +60,6 @@ internal fun MainView(
@Composable
internal fun MainState.MainViewImpl(
gameSettings: GameSettings,
windowSizeClass: WindowSizeClass,
startDestination: String = MainRoutes.Start,
) {
val viewModelStoreOwner = requireNotNull(LocalViewModelStoreOwner.current) {
Expand Down Expand Up @@ -100,30 +90,17 @@ internal fun MainState.MainViewImpl(
)
}

val shouldShowBottomBar = with(windowSizeClass) {
widthSizeClass == WindowWidthSizeClass.Compact || heightSizeClass == WindowHeightSizeClass.Compact
}
val shouldShowNavRail = !shouldShowBottomBar
val destinationModifier = Modifier.fillMaxSize()

Scaffold(
topBar = {
MainTopAppBar(currentDestination, navController, gameSettings)
},
bottomBar = {
if (shouldShowBottomBar) {
BottomAppBar { NavigationActions(currentDestination, ::navigateTo) }
}
},
) { innerPadding ->
Row(
NavigationSuiteScaffold(
navigationSuiteItems = { navigationActions(currentDestination, ::navigateTo) },
modifier = Modifier.padding(innerPadding),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
if (shouldShowNavRail) {
NavigationRail { NavigationActions(currentDestination, ::navigateTo) }
}

NavHost(
navController = navController,
startDestination = startDestination,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
package com.ekezet.othello.main.ui.components

import androidx.compose.material3.Icon
import androidx.compose.material3.IconToggleButton
import androidx.compose.runtime.Composable
import androidx.compose.material3.Text
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScope
import androidx.compose.ui.res.stringResource
import com.ekezet.othello.main.navigation.MainRoutes

@Composable
internal fun NavigationActions(currentDestination: String, onClick: (String) -> Unit) {
internal fun NavigationSuiteScope.navigationActions(currentDestination: String, onClick: (String) -> Unit) {
MainRoutes.All.forEach { destination ->
IconToggleButton(
checked = currentDestination == destination.id,
onCheckedChange = { onClick(destination.id) },
) {
Icon(
imageVector = destination.icon,
contentDescription = null,
)
}
item(
icon = {
Icon(
imageVector = destination.icon,
contentDescription = stringResource(id = destination.labelRes)
) },
label = { Text(text = stringResource(id = destination.labelRes)) },
selected = currentDestination == destination.id,
onClick = { onClick(destination.id) },
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.navigation.NamedNavArgument
abstract class Route {
abstract val id: String
abstract val icon: ImageVector
abstract val labelRes: Int

open val spec: String
get() = id
Expand Down
2 changes: 2 additions & 0 deletions core/ui/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
<string name="main__menu__new_game">Reset game</string>
<string name="main__menu__share_board">Share board</string>
<string name="main__menu__toggle_indicators">Toggle indicators</string>
<string name="main__nav__game_board">Game</string>
<string name="main__nav__game_settings">Settings</string>

<string name="common__dark">Dark</string>
<string name="common__human_player">Human Player</string>
Expand Down
8 changes: 5 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ androidGradlePlugin = "8.4.1"
androidxActivity = "1.9.0"
androidxAppCompat = "1.6.1"
androidxComposeBom = "2024.05.00"
androidxComposeMaterial3 = "1.3.0-beta01"
androidxComposeRuntimeTracing = "1.0.0-beta01"
androidxCore = "1.13.1"
androidxLifecycle = "2.8.0"
Expand All @@ -15,8 +16,8 @@ koinBom = "3.5.1"
konfetti = "2.0.3"
kotlin = "2.0.0"
kotlinxCoroutines = "1.8.1"
kotlinxKover = "0.8.0"
kotlinxImmutable = "0.3.7"
kotlinxKover = "0.8.0"
ksp = "1.9.22-1.0.17"
mockk = "1.13.8"
timber = "5.0.1"
Expand All @@ -29,8 +30,9 @@ androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", versi
androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation" }
androidx-compose-foundation-layout = { group = "androidx.compose.foundation", name = "foundation-layout" }
androidx-compose-material-iconsExtended = { group = "androidx.compose.material", name = "material-icons-extended" }
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-compose-material3-windowSizeClass = { group = "androidx.compose.material3", name = "material3-window-size-class" }
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "androidxComposeMaterial3" }
androidx-compose-material3-windowSizeClass = { group = "androidx.compose.material3", name = "material3-window-size-class", version.ref = "androidxComposeMaterial3" }
androidx-compose-material3-adaptiveNavigationSuite = { group = "androidx.compose.material3", name = "material3-adaptive-navigation-suite", version.ref = "androidxComposeMaterial3" }
androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime" }
androidx-compose-runtime-tracing = { group = "androidx.compose.runtime", name = "runtime-tracing", version.ref = "androidxComposeRuntimeTracing" }
androidx-compose-ui-test = { group = "androidx.compose.ui", name = "ui-test-junit4" }
Expand Down

0 comments on commit 97aca65

Please sign in to comment.