Навигация по типам с вложенными графиками, навигацией и инклюзивным всплыванием в JetPack ComposeAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Навигация по типам с вложенными графиками, навигацией и инклюзивным всплыванием в JetPack Compose

Сообщение Anonymous »

Существует ли правильный пример навигации, защищенной от типов с вложенными графиками, где один из графов включает в себя навигационный балл с собственными экранами, а экран Auth/Splash/Onbarting удаляется из заднего стека, используя Inclusive = True, все без дублирования MamplicatingNavController/NAVHOST?@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
IncomeTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
NavigationHost()
}
}
}
}
}

@Serializable
sealed class Graph {
@Serializable
object OnboardingGraph : Graph()

@Serializable
object MainGraph : Graph()
}

@Serializable
sealed class OnboardingGraph {
@Serializable
object OnboardingScreen : OnboardingGraph()
}

@Serializable
sealed class MainGraph {
@Serializable
object Home : MainGraph()
@Serializable
object Notification : MainGraph()
@Serializable
object History : MainGraph()
@Serializable
object Settings : MainGraph()
}

enum class TopLevelRoute(
val route: Any,
@StringRes val label: Int,
@DrawableRes val iconFill: Int
) {
HOME(
MainGraph.Home,
R.string.tab_home,
R.drawable.baseline_home_24
),
NOTIFICATION(
MainGraph.Notification,
R.string.tab_notification,
R.drawable.baseline_notifications_24
),
HISTORY(
MainGraph.History,
R.string.tab_history,
R.drawable.baseline_history_edu_24
),
SETTINGS(
MainGraph.Settings,
R.string.tab_settings,
R.drawable.baseline_settings_24
);
}

@Composable
fun BottomNavigationBar(
navController: NavHostController,
currentDestination: NavDestination?
) {

NavigationBar {
TopLevelRoute.entries.forEach { navigationItem ->
NavigationBarItem(
selected = currentDestination?.hierarchy?.any {
it.hasRoute(navigationItem.route::class)
} == true,
label = {
Text(text = stringResource(navigationItem.label))
},
icon = {
Icon(
painterResource(navigationItem.iconFill),
contentDescription = stringResource(navigationItem.label)
)
},
onClick = {
navController.navigate(navigationItem.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
)
}
}
}

@Composable
private fun NavigationHost() {
val navController = rememberNavController()

NavHost(
navController = navController,
startDestination = Graph.OnboardingGraph,
enterTransition = { EnterTransition.None },
exitTransition = { ExitTransition.None }
) {
onboardingNavGraph(navController)

composable {
MainScreenUI(navController = navController)
}
}
}

fun NavGraphBuilder.onboardingNavGraph(
navController: NavController
) {
navigation(startDestination = OnboardingGraph.OnboardingScreen) {
composable {
OnboardingScreen(
onFinished = {
navController.navigate(MainGraph.Home) {
popUpTo(OnboardingGraph.OnboardingScreen) {
inclusive = true
}
}
}
)
}
}
}

@Composable
fun MainScreenUI(
navController: NavHostController
) {
val navController = rememberNavController()

val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination

Scaffold(
modifier = Modifier.fillMaxSize(),
bottomBar = {
BottomNavigationBar(
navController = navController,
currentDestination = currentDestination
)
}
) { paddingValues ->
NavHost(
modifier = Modifier.padding(paddingValues),
navController = navController,
startDestination = Graph.MainGraph,
enterTransition = { EnterTransition.None },
exitTransition = { ExitTransition.None }
) {
mainNavGraph(navController)
}
}
}

fun NavGraphBuilder.mainNavGraph(
navController: NavController
) {
navigation(startDestination = MainGraph.Home) {
composable {
HomeScreen { /* TODO */ }
}
composable {
NotificationScreen { /* TODO */ }
}
composable {
HistoryScreen { /* TODO */ }
}
composable {
SettingsScreen { /* TODO */ }
}
}
}
< /code>
также попробовал использование одного навигации с двумя вложенными графиками, но вызов: < /p>
navController.navigate(MainGraph.Home) {
popUpTo(OnboardingGraph.OnboardingScreen) {
inclusive = true
}
}
< /code>
Приводит к ошибке:
«Игнорирование Popbackstack в пункт назначения xxxxxx, так как он не был найден в текущем заднем стеке» < /strong>,
, а также мерцание экранов при снова навигации на тот же экран. Ошибка возникает из -за того, что при нажатии на нижний элемент навигации метод всплывающего количества вызывается с помощью начального идентификатора назначения, который определяется с использованием NavController.graph.findStartDestination (). ID. Тем не менее, начальное место назначения графика остается экраном адаптации, который уже был удален из заднего стека после его завершения. В результате предпринимается попытка «всплыть» на экран, который больше не существует в стеке. (В случае попытки использовать два строителя графика с одним навигацией) в настоящее время я вижу решение, установив экран maingraph \ home
в качестве пункта назначения в нижней навигации вместо использования FindStartDestination () . Однако я не уверен, является ли это лучшей практикой. < /P>

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
IncomeTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
MainScreenUI()
}
}
}
}
}

@Serializable
sealed class Graph {
@Serializable
object OnboardingGraph : Graph()

@Serializable
object MainGraph : Graph()
}

@Serializable
sealed class OnboardingGraph {
@Serializable
object OnboardingScreen : OnboardingGraph()
}

@Serializable
sealed class MainGraph {
@Serializable
object Home : MainGraph()
@Serializable
object Notification : MainGraph()
@Serializable
object History : MainGraph()
@Serializable
object Settings : MainGraph()
}

enum class TopLevelRoute(
val route: Any,
@StringRes val label: Int,
@DrawableRes val iconFill: Int
) {
HOME(
MainGraph.Home,
R.string.tab_home,
R.drawable.baseline_home_24
),
NOTIFICATION(
MainGraph.Notification,
R.string.tab_notification,
R.drawable.baseline_notifications_24
),
HISTORY(
MainGraph.History,
R.string.tab_history,
R.drawable.baseline_history_edu_24
),
SETTINGS(
MainGraph.Settings,
R.string.tab_settings,
R.drawable.baseline_settings_24
);
}

@Composable
fun MainScreenUI() {
val navController = rememberNavController()
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination

Scaffold(
modifier = Modifier.fillMaxSize(),
bottomBar = {
// distance check to exclude non-incoming screens
BottomNavigationBar(
navController = navController,
currentDestination = currentDestination
)
}
) { paddingValues ->
NavHost(
modifier = Modifier.padding(paddingValues),
navController = navController,
startDestination = Graph.OnboardingGraph,
enterTransition = { EnterTransition.None },
exitTransition = { ExitTransition.None }
) {
onboardingNavGraph(navController)
mainNavGraph(navController)
}
}
}

@Composable
fun BottomNavigationBar(
navController: NavHostController,
currentDestination: NavDestination?
) {
NavigationBar {
TopLevelRoute.entries.forEach { navigationItem ->
NavigationBarItem(
selected = currentDestination?.hierarchy?.any {
it.hasRoute(navigationItem.route::class)
} == true,
label = {
Text(text = stringResource(navigationItem.label))
},
icon = {
Icon(
painterResource(navigationItem.iconFill),
contentDescription = stringResource(navigationItem.label)
)
},
onClick = {
navController.navigate(navigationItem.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
)
}
}
}

fun NavGraphBuilder.onboardingNavGraph(
navController: NavController
) {
navigation(startDestination = OnboardingGraph.OnboardingScreen) {
composable {
OnboardingScreen(
onFinished = {
navController.navigate(MainGraph.Home) {
popUpTo(OnboardingGraph.OnboardingScreen) {
inclusive = true
}
}
}
)
}
}
}

fun NavGraphBuilder.mainNavGraph(
navController: NavController
) {
navigation(startDestination = MainGraph.Home) {
composable {
HomeScreen { /* TODO */ }
}
composable {
NotificationScreen { /* TODO */ }
}
composable {
HistoryScreen { /* TODO */ }
}
composable {
SettingsScreen { /* TODO */ }
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/795 ... popup-in-j
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»