https://kotlinlang.org logo
#compose
Title
# compose
i

izyaboi

11/02/2020, 10:49 AM
one question about navigation compose how can i implement the navigation. I have a one activity app with navigation bottom an a detail that behavior like an actvity. but ive i implement the detail screen composable in the navhost without activity. The behavior is diffrent
Copy code
NavHost(navController, startDestination = NavigationScreen.Home.route) {
    composable(NavigationScreen.Home.route) { Home(navController) }
    composable(NavigationScreen.Playlist.route) { Playlist() }
    composable(Screen.Detail.route) { DetailScreen()}
}
navigation works but not like i implement it as second activity with start activity.
l

loloof64

11/02/2020, 11:09 AM
Hi, I don't think I've well understood your question. But have you checked https://developer.android.com/jetpack/compose/navigation ?
i

izyaboi

11/02/2020, 11:12 AM
the problem is that my detail composable dont behavoir like if i call it as an actvity. the content is above the bottom navigation not like if i use a extra actvity. fullscreen u understand?
l

loloof64

11/02/2020, 11:14 AM
A bit more, I think. Are you using a Scaffold in the main composable ?
i

izyaboi

11/02/2020, 11:18 AM
si ,
Copy code
@Composable
fun MainScreen() {
    val items = listOf(
        NavigationScreen.Home,
        NavigationScreen.Playlist,
    )
    val navController = rememberNavController()
    Scaffold(
        bottomBar = {
            BottomNavigation (
                    modifier = Modifier.navigationBarsPadding(left = false, right = false)
            ){
                val navBackStackEntry by navController.currentBackStackEntryAsState()
                val currentRoute = navBackStackEntry?.arguments?.getString(KEY_ROUTE)
                items.forEach { screen ->
                    val selected = currentRoute == screen.route
                    BottomNavigationItem(
                        icon = {
                            when {
                                selected -> Icon(screen.selectedIcon)
                                else -> Icon (screen.icon)
                            }
                        },
                        label = { Text(stringResource(screen.resourceId)) },
                        selected = selected,
                        onClick = {
                            // This is the equivalent to popUpTo the start destination
                            navController.popBackStack(
                                navController.graph.startDestination,
                                false
                            )

                            // This if check gives us a "singleTop" behavior where we do not create a
                            // second instance of the composable if we are already on that destination
                            if (currentRoute != screen.route) {
                                navController.navigate(screen.route)
                            }
                        }
                    )
                }
            }
        }
    ) {

        NavHost(navController, startDestination = NavigationScreen.Home.route) {
            composable(NavigationScreen.Home.route) { Home(navController) }
            composable(NavigationScreen.Playlist.route) { Playlist() }
            composable(Screen.Detail.route) { DetailScreen(navController)}
        }
    }
}
it make sense that DetailScreen behavior is the same as the naviagtion items playlist and Home but how can i implement detail behavior l(ike a extra Activity) but without to use a extra acitvity (one activity app)
z

ziv kesten

11/02/2020, 12:08 PM
Create a composable for your app with it’s own navController, it will navigate the details screen and the main screen. In your MainScreen you should remember a different navController that will navigate the bottom items screens, i will post a blog with examples and link here shortly
1
👍 1
class MainActivity : AppCompatActivity() { @ExperimentalCoroutinesApi @FlowPreview @VisibleForTesting val viewModel = MainViewModel() @FlowPreview @ExperimentalAnimationApi override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { TrackShowsTheme() { TrackShowsApp(viewModel = viewModel) } } }
Copy code
TrackShowsApp implementation

@Composable
fun TrackShowsApp(viewModel: MainViewModel) {
    val navController = rememberNavController()
    navigationConfigurations(navController, viewModel, initialScreen = AppScreens.Main.route) // Declare the navigation flows
    handleNavigationActions(viewModel, navController) // Act on navigation actions flow
}

@ExperimentalCoroutinesApi
@FlowPreview
@ExperimentalAnimationApi
@Composable
private fun navigationConfigurations(

    navController: NavHostController,
    viewModel: MainViewModel,
    initialScreen: String,
) {
    NavHost(navController, startDestination = initialScreen) {
        composable(AppScreens.Main.route) {
            MainScreen(viewModel)
        }
        composable(AppScreens.Details.route) {
            ShowDetails(viewModel)
        }
        composable(AppScreens.Search.route) {
            SearchScreen(viewModel)
        }
    }
}

@ExperimentalCoroutinesApi
@FlowPreview
@Composable
private fun handleNavigationActions(viewModel: MainViewModel, navController: NavHostController) {
    CoroutineScope(Dispatchers.Main).launch {
        viewModel.navigateTo.collect {
            navController.navigate(it.route)
        }
    }
}
MainScreen
Copy code
@Composable
fun MainScreen(viewModel: MainViewModel) {
    val navController = rememberNavController()
    val bottomNavigationItems = listOf(
        BottomNavigationScreens.WatchList,
        BottomNavigationScreens.MyShows,
        BottomNavigationScreens.Discover,
        BottomNavigationScreens.Statistics
    )
    Scaffold(
        topBar = { TrackShowsTopBar() },
        bottomBar = { TrackShowsBottomNavigation(navController, bottomNavigationItems) },
        floatingActionButton = { TrackShowsFloatingActionButton(navController) },
        floatingActionButtonPosition = FabPosition.End
    ) {
        MainScreenNavigationConfigurations(navController, viewModel)
    }
}

@ExperimentalCoroutinesApi
@FlowPreview
@ExperimentalAnimationApi
@Composable
private fun MainScreenNavigationConfigurations(
    navController: NavHostController,
    viewModel: MainViewModel
) {
    NavHost(navController, startDestination = BottomNavigationScreens.WatchList.route) {
        composable(BottomNavigationScreens.WatchList.route) {
            WatchList(viewModel)
            CustomView()
        }
        composable(BottomNavigationScreens.MyShows.route) {
            MyShows(viewModel = viewModel)
        }
        composable(BottomNavigationScreens.Discover.route) {
            DiscoverScreen(viewModel)
        }
        composable(BottomNavigationScreens.Statistics.route) {
            WatchList(viewModel)
        }
    }
}
BottomNavigation
Copy code
@Composable
private fun TrackShowsBottomNavigation(
    navController: NavHostController,
    items: List<BottomNavigationScreens>
) {
    BottomNavigation {
        val currentRoute = currentRoute(navController)
        items.forEach { screen ->
            BottomNavigationItem(
                icon = {
                    when (screen) {
                        is BottomNavigationScreens.WatchList -> Icon(Icons.Filled.Terrain)
                        is BottomNavigationScreens.MyShows -> Icon(Icons.Filled.Satellite)
                        is BottomNavigationScreens.Discover -> Icon(Icons.Filled.LocalSee)
                        is BottomNavigationScreens.Statistics -> Icon(Icons.Filled.ChargingStation)
                    }
                },
                label = { Text(stringResource(id = screen.resourceId)) },
                selected = currentRoute == screen.route,
                alwaysShowLabels = false,
                onClick = {
                    // This if check gives us a "singleTop" behavior where we do not create a
                    // second instance of the composable if we are already on that destination
                    if (currentRoute != screen.route) {
                        Log.d("Zivi", "navigate to: ${screen.route}")
                        navController.navigate(screen.route)
                    }
                }
            )
        }
    }
}

@Composable
private fun currentRoute(
    navController: NavHostController
): String? {
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    return navBackStackEntry?.arguments?.getString(KEY_ROUTE)
}
3 Views