Заложена навигация с передачей параметров и сохранением состояний
This commit is contained in:
@@ -1,14 +1,30 @@
|
||||
package com.github.nullptroma.wallenc.presentation
|
||||
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Menu
|
||||
import androidx.compose.material.icons.rounded.Settings
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.toRoute
|
||||
import com.github.nullptroma.wallenc.presentation.navigation.NavBarItem
|
||||
import com.github.nullptroma.wallenc.presentation.navigation.rememberNavigationState
|
||||
import com.github.nullptroma.wallenc.presentation.screens.main.MainRoute
|
||||
import com.github.nullptroma.wallenc.presentation.screens.main.MainScreen
|
||||
import com.github.nullptroma.wallenc.presentation.screens.settings.SettingsRoute
|
||||
@@ -25,17 +41,70 @@ fun WallencUi() {
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun WallencNavRoot() {
|
||||
val navController = rememberNavController()
|
||||
Scaffold { innerPaddings ->
|
||||
NavHost(navController, startDestination = MainRoute()) {
|
||||
composable<MainRoute> {
|
||||
val navState = rememberNavigationState()
|
||||
|
||||
val topLevelScreenRoutes = rememberSaveable {
|
||||
mutableMapOf(
|
||||
MainRoute::class.qualifiedName!! to MainRoute(),
|
||||
SettingsRoute::class.qualifiedName!! to SettingsRoute("Base settings")
|
||||
)
|
||||
}
|
||||
|
||||
// Все пункты меню верхнего уровня
|
||||
val topLevelNavBarItems = remember {
|
||||
listOf(
|
||||
NavBarItem("Main", MainRoute::class.qualifiedName!!, Icons.Rounded.Menu),
|
||||
NavBarItem("Settings", SettingsRoute::class.qualifiedName!!, Icons.Rounded.Settings)
|
||||
)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
bottomBar = {
|
||||
NavigationBar {
|
||||
val navBackStackEntry by navState.navHostController.currentBackStackEntryAsState()
|
||||
val currentRoute = navBackStackEntry?.destination?.route
|
||||
topLevelNavBarItems.forEach {
|
||||
val routeClassName = it.screenRouteClass
|
||||
|
||||
NavigationBarItem(
|
||||
icon = {
|
||||
Icon(
|
||||
it.icon,
|
||||
contentDescription = it.name
|
||||
)
|
||||
},
|
||||
label = { Text(it.name) },
|
||||
selected = currentRoute?.startsWith(routeClassName) == true,
|
||||
onClick = {
|
||||
var route = topLevelScreenRoutes[it.screenRouteClass]
|
||||
if(route == null)
|
||||
throw NoSuchElementException("Screen route of type ${it.screenRouteClass} no found")
|
||||
if(currentRoute?.startsWith(routeClassName) != true)
|
||||
navState.navigationTo(route)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}) { innerPaddings ->
|
||||
NavHost(navState.navHostController, startDestination = topLevelScreenRoutes[MainRoute::class.qualifiedName]!!) {
|
||||
composable<MainRoute>(enterTransition = {
|
||||
fadeIn(tween(200))
|
||||
}, exitTransition = {
|
||||
fadeOut(tween(200))
|
||||
}) {
|
||||
MainScreen(Modifier.padding(innerPaddings), onSettingsRoute = { settingsRoute ->
|
||||
navController.navigate(settingsRoute)
|
||||
topLevelScreenRoutes[settingsRoute::class.qualifiedName!!] = settingsRoute
|
||||
navState.navigationTo(settingsRoute)
|
||||
})
|
||||
}
|
||||
composable<SettingsRoute> {
|
||||
composable<SettingsRoute>(enterTransition = {
|
||||
fadeIn(tween(200))
|
||||
}, exitTransition = {
|
||||
fadeOut(tween(200))
|
||||
}) {
|
||||
val route: SettingsRoute = it.toRoute()
|
||||
SettingsScreen(Modifier.padding(innerPaddings), route.text)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.github.nullptroma.wallenc.presentation.navigation
|
||||
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
|
||||
data class NavBarItem(val name: String, val screenRouteClass: String, val icon: ImageVector)
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.github.nullptroma.wallenc.presentation.navigation
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.github.nullptroma.wallenc.presentation.screens.ScreenRoute
|
||||
|
||||
|
||||
class NavigationState(
|
||||
val navHostController: NavHostController
|
||||
) {
|
||||
fun navigationTo(route: ScreenRoute) {
|
||||
navHostController.navigate(route) {
|
||||
popUpTo(navHostController.graph.findStartDestination().id)
|
||||
launchSingleTop = true
|
||||
restoreState = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberNavigationState(
|
||||
navHostController: NavHostController? = null
|
||||
): NavigationState {
|
||||
val controller = navHostController ?: rememberNavController()
|
||||
return remember { NavigationState(controller) }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.github.nullptroma.wallenc.presentation.screens
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
abstract class ScreenRoute() : Parcelable
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.github.nullptroma.wallenc.presentation.screens.main
|
||||
|
||||
import com.github.nullptroma.wallenc.presentation.screens.ScreenRoute
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable class MainRoute
|
||||
@Serializable
|
||||
@Parcelize
|
||||
class MainRoute: ScreenRoute()
|
||||
@@ -9,10 +9,11 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.github.nullptroma.wallenc.presentation.screens.settings.SettingsRoute
|
||||
|
||||
@@ -22,12 +23,14 @@ fun MainScreen(modifier: Modifier = Modifier,
|
||||
viewModel: MainViewModel = hiltViewModel(),
|
||||
onSettingsRoute: (SettingsRoute) -> Unit) {
|
||||
val state = viewModel.stateFlow
|
||||
var text by remember { mutableStateOf("") }
|
||||
var text by rememberSaveable { mutableStateOf("") }
|
||||
val focusManager = LocalFocusManager.current
|
||||
Column(modifier = modifier.imePadding().fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center) {
|
||||
TextField(text, onValueChange = { s ->
|
||||
text = s
|
||||
})
|
||||
Button( onClick = {
|
||||
focusManager.clearFocus()
|
||||
onSettingsRoute(SettingsRoute(text))
|
||||
}) {
|
||||
Text("Press Me!")
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.github.nullptroma.wallenc.presentation.screens.settings
|
||||
|
||||
import com.github.nullptroma.wallenc.presentation.screens.ScreenRoute
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable class SettingsRoute(val text: String)
|
||||
@Serializable
|
||||
@Parcelize
|
||||
class SettingsRoute(val text: String): ScreenRoute()
|
||||
|
||||
Reference in New Issue
Block a user