android-jetpack-composelazycolumnnavigation-compose

Problem opening different screen for the list of data items using jetpack Compose


Clicking on item 1 opens Screen1, Clicking on item 2 opens Screen1, Clicking on item 3 opens Screen1,

Instead the folowing should happed:

Clicking on item 1 should open Screen1, Clicking on item 2 should open Screen2, Clicking on item 3 should open Screen3,

Where am i going wrong.

Data Item: data class DataItem(val text: String, val imageResId: Int)

List of data item: val dataItems = listOf( DataItem("Item 1", R.drawable.concrete), DataItem("Item 2", R.drawable.plaster), DataItem("Item 3", R.drawable.blocks) )

Screen 1 @Composable fun Screen1(navController: NavController, dataItem: DataItem) { Column( modifier = Modifier .fillMaxSize() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text(text = "Screen 1") Spacer(modifier = Modifier.height(16.dp)) Image( painter = painterResource(id = dataItem.imageResId), contentDescription = null, modifier = Modifier .size(200.dp) .clip(shape = MaterialTheme.shapes.medium) .background(MaterialTheme.colorScheme.primary) ) Spacer(modifier = Modifier.height(16.dp)) Text(text = dataItem.text) } }

Screen 2 @Composable fun Screen2(navController: NavController, dataItem: DataItem) { Column( modifier = Modifier .fillMaxSize() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text(text = "Screen 2") Spacer(modifier = Modifier.height(16.dp)) Image( painter = painterResource(id = dataItem.imageResId), contentDescription = null, modifier = Modifier .size(200.dp) .clip(shape = MaterialTheme.shapes.medium) .background(MaterialTheme.colorScheme.primary) ) Spacer(modifier = Modifier.height(16.dp)) Text(text = dataItem.text) } }

Screen 3 @Composable fun Screen3(navController: NavController, dataItem: DataItem) { Column( modifier = Modifier .fillMaxSize() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text(text = "Screen 3") Spacer(modifier = Modifier.height(16.dp)) Image( painter = painterResource(id = dataItem.imageResId), contentDescription = null, modifier = Modifier .size(200.dp) .clip(shape = MaterialTheme.shapes.medium) .background(MaterialTheme.colorScheme.primary) ) Spacer(modifier = Modifier.height(16.dp)) Text(text = dataItem.text) } }

Data List Screen, This screen will be displayed on the main screen @Composable fun DataList(navController: NavController) { LazyColumn { items(dataItems) { item -> Box( modifier = Modifier .fillMaxWidth() .clickable { navController.navigate("screen1/${dataItems.indexOf(item)}") } ) { Row( modifier = Modifier .fillMaxWidth() .padding(16.dp), verticalAlignment = Alignment.CenterVertically ) { Image( painter = painterResource(id = item.imageResId), contentDescription = null, modifier = Modifier .size(64.dp) .clip(shape = MaterialTheme.shapes.medium) .background(MaterialTheme.colorScheme.primary) ) Spacer(modifier = Modifier.width(16.dp)) Text(text = item.text) } } } } }

`@Composable fun MyApp() { val navController = rememberNavController()

NavHost(navController, startDestination = "dataList") {
    composable("dataList") {
        DataList(navController = navController)
    }
    composable(
        route = "screen1/{index}",
        arguments = listOf(navArgument("index") { type = NavType.IntType })
    ) { backStackEntry ->
        val index = backStackEntry.arguments?.getInt("index")
        val dataItem = if (index != null && index < dataItems.size) dataItems[index] else dataItems[0]
        Screen1(navController = navController, dataItem = dataItem)
    }
    composable(
        route = "screen2/{index}",
        arguments = listOf(navArgument("index") { type = NavType.IntType })
    ) { backStackEntry ->
        val index = backStackEntry.arguments?.getInt("index")
        val dataItem = if (index != null && index < dataItems.size) dataItems[index] else dataItems[0]
        Screen2(navController = navController, dataItem = dataItem)
    }
    composable(
        route = "screen3/{index}",
        arguments = listOf(navArgument("index") { type = NavType.IntType })
    ) { backStackEntry ->
        val index = backStackEntry.arguments?.getInt("index")
        val dataItem = if (index != null && index < dataItems.size) dataItems[index] else dataItems[0]
        Screen3(navController = navController, dataItem = dataItem)
    }
}

}`

Each list item should open the screen corresponding to it.


Solution

  • In the Data List Screen u have the following line

    navController.navigate("screen1/${dataItems.indexOf(item)}")
    

    instead of hardcoded screen1 u should pass the index (or id) of the screen, like

    navController.navigate("screen${index}/${dataItems.indexOf(item)}")