Jetpack Compose:如何显示带有来自 LazyColumn 单击项目的单个项目信息的警报对话框?

Jetpack Compose: How to show Alert Dialog with a single item's information from LazyColumn clicked item?

我正在做一个简单的项目,在这个项目中我导入了一个有空间的库存项目数据库,并且可以根据变化修改库存。我正在与 LazyColumn.

作斗争

我需要的是:单击 LazyColumn 中的项目时,显示带有项目信息的警告对话框。 会发生什么:单击 LazyColumn 中的项目时,它会显示所有项目警报对话框(生成 100 多个警报对话框,只有最后一个可见)。

应用主页LazyColumn

点击项目后显示 100 多个警告对话框的巨大阴影,只有最后一个项目可见:

//custom alert dialog taking parameters from the database class of the inventory items

@Composable
fun ItemAlertDialog(
    onDismiss: () -> Unit,
    onNegativeClick: () -> Unit,
    onPositiveClick: () -> Unit,
    currentInventory: Int,
    itemDescription: String,
    itemNumber: String,
) {
    var incoming by remember { mutableStateOf(0f) }
    var outgoing by remember { mutableStateOf(0f) }

    Dialog(onDismissRequest = onDismiss) {
        Card(
            elevation = 8.dp,
            shape = RoundedCornerShape(12.dp)
        ) {
            Column(modifier = Modifier.padding(8.dp)) {
                Text(
                    text = itemNumber,
                    fontWeight = FontWeight.Bold,
                    fontSize = 20.sp,
                    modifier = Modifier.padding(8.dp)
                )
                Spacer(modifier = Modifier.height(8.dp))

                Text(
                    text = itemDescription,
                    fontWeight = FontWeight.Normal,
                    fontSize = 15.sp,
                    modifier = Modifier.padding(8.dp)
                )
                Spacer(modifier = Modifier.height(8.dp))
                Text(
                    text = currentInventory.toString(),
                    fontWeight = FontWeight.ExtraBold,
                    color = Color(0xFF0FFC107),
                    fontSize = 20.sp,
                    modifier = Modifier.padding(8.dp)
                )
                // Update Inventory
                Row(
                    verticalAlignment = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.Center
                ) {
                    Column {

                        Text(text = "Incoming ${incoming.toInt()}")
                        Slider(
                            value = incoming,
                            onValueChange = { incoming = it },
                            valueRange = 0f..100f,
                            onValueChangeFinished = {}
                        )
                        Spacer(modifier = Modifier.height(8.dp))

                        Text(text = "Outgoing ${outgoing.toInt()}")
                        Slider(
                            value = outgoing,
                            onValueChange = { outgoing = it },
                            valueRange = 0f..100f,
                            onValueChangeFinished = {}
                        )
                    }
                }

                // Buttons
                Row(
                    horizontalArrangement = Arrangement.End,
                    modifier = Modifier.fillMaxWidth()
                ) {
                    TextButton(onClick = onNegativeClick) {
                        Text(text = "CANCEL")
                    }
                    Spacer(modifier = Modifier.width(4.dp))
                    TextButton(onClick = {
                        onPositiveClick.invoke()
                    }) {
                        Text(text = "OK")
                    }
                }
            }
        }
    }
}

带有 onclick 的项目行代码我想通过以下方式触发对话框:

@Composable
fun MainScreenItemRow(
    itemNumber: String,
    itemDescription: String,
    currentInventory: Int,
    onclick: () -> Unit
) {
    Row(modifier = Modifier
        .clickable {
            onclick.invoke()
        }
        .border(width = 1.dp, color = Color.Gray, shape = RoundedCornerShape(8.dp))
        .padding(16.dp)
        .clip(shape = RoundedCornerShape(8.dp)),
        horizontalArrangement = Arrangement.SpaceBetween,
        verticalAlignment = Alignment.CenterVertically
    ) {
        Text(
            text = itemNumber,
            fontSize = 12.sp,
            fontWeight = FontWeight.Bold,
            modifier = Modifier.weight(3f)
        )
        Spacer(modifier = Modifier.width(10.dp))

        Text(
            text = itemDescription,
            fontSize = 12.sp,
            maxLines = 3,
            modifier = Modifier.weight(4f)
        )
        Spacer(modifier = Modifier.width(30.dp))

        Text(
            text = currentInventory.toString(),
            fontSize = 20.sp,
            color = Color(0xFF0FFC107),
            modifier = Modifier.weight(1f)
        )
    }
}

MainActivity 代码(对乱码表示歉意,注释有//***):

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

    private val mainViewModel: MainViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {

            val systemUiController = rememberSystemUiController()
            val useDarkIcons = MaterialTheme.colors.isLight
            val inventoryList by mainViewModel.getInventoryItems.collectAsState(initial = emptyList()) 
            val showItemDialog = remember { mutableStateOf(false)}
            val result = remember { mutableStateOf("") }
            val expanded = remember { mutableStateOf(false) }
            val randomList = listOf("")
            val selectedItem = remember{ mutableStateOf(randomList[0])}

//*** getting inventoryList from the flow, added remember to selectedItem and showItemDialog

            SimpleInventoryTheme {
                ItemModelDrawer{drawerState, drawerScopeState ->
                    SideEffect {
                        systemUiController.setSystemBarsColor(
                            color = Color.Transparent,
                            darkIcons = useDarkIcons
                        )
                    }

                    Scaffold(
                        topBar = {
                            TopAppBar(
                                title = {
                                    Text(text = "Inventory Manager")
                                },
                                actions = {
                                    IconButton(onClick = {
                                        drawerScopeState.launch {
                                            drawerState.open()
                                        }
                                    }) {
                                        Icon(Icons.Outlined.Search, contentDescription = "Search")
                                    }

                                    Box(
                                        Modifier
                                            .wrapContentSize(Alignment.TopEnd)
                                    ) {
                                        IconButton(onClick = {
                                            expanded.value = true
                                            result.value = "More icon clicked"
                                        }) {
                                            Icon(
                                                Icons.Filled.MoreVert,
                                                contentDescription = "Localized description"
                                            )
                                        }

                                        DropdownMenu(
                                            expanded = expanded.value,
                                            onDismissRequest = { expanded.value = false },
                                        ) {
                                            DropdownMenuItem(onClick = {
                                                expanded.value = false
                                                result.value = "First item clicked"
                                            }) {
                                                Text("First Item")
                                            }

                                            Divider()

                                            DropdownMenuItem(onClick = {
                                                expanded.value = false
                                                result.value = "Second item clicked"
                                            }) {
                                                Text("Second item")
                                            }

                                        }
                                    }
                                },

                                backgroundColor = Color.White,
                                elevation = AppBarDefaults.TopAppBarElevation
                            )
                        },

                        content = {
                            Column(modifier = Modifier.fillMaxSize()) {
                                MainScreenTitlesRow()
                                Divider()

//*** Showing the items in the main page and adding onclick to fire up the alert dialog 
                               
                                LazyColumn(
                                    verticalArrangement = Arrangement.spacedBy(8.dp),
                                    modifier = Modifier
                                        .fillMaxSize()
                                        .padding(16.dp)
                                ) {

                                    itemsIndexed(inventoryList) { idx, item ->
                                        item.currentInventory?.let {
                                            MainScreenItemRow(
                                                itemNumber = item.itemNumber,
                                                itemDescription = item.itemDescription,
                                                currentInventory = it,
                                                onclick = {
//*** trying to set the clicked item into "selectedItem" val
 
                                                    selectedItem.value = item.itemNumber
                                                    selectedItem.value = item.itemDescription
                                                    selectedItem.value = item.currentInventory.toString()
                                                    Log.d("MainActivityItemClicked", "$selectedItem ")
                                                    showItemDialog.value = true
                                                }
                                            )
                                        }
                                    }


                                }

//*** Trying to check which item was clicked and only present its information in the alert dialog but it loads up all the items

                                if (showItemDialog.value) {

                                    LazyColumn {
                                        itemsIndexed(inventoryList) { _, item ->
                                            item.currentInventory?.let {
                                                ItemAlertDialog(
                                                    itemNumber = item.itemNumber,
                                                    itemDescription = item.itemDescription,
                                                    currentInventory = it,
                                                    onDismiss = {
                                                        showItemDialog.value = !showItemDialog.value
                                                        Toast.makeText(
                                                            this@MainActivity,
                                                            "Dialog dismissed!",
                                                            Toast.LENGTH_SHORT
                                                        )
                                                            .show()
                                                    },
                                                    onNegativeClick = {
                                                        showItemDialog.value = !showItemDialog.value
                                                        Toast.makeText(
                                                            this@MainActivity,
                                                            "Cancel!",
                                                            Toast.LENGTH_SHORT
                                                        )
                                                            .show()

                                                    },
                                                    onPositiveClick = {
                                                        showItemDialog.value = !showItemDialog.value
                                                        Toast.makeText(
                                                            this@MainActivity,
                                                            "Saved!",
                                                            Toast.LENGTH_SHORT
                                                        )
                                                            .show()
                                                    }
                                                )
                                            }

                                        }
                                    }


                                }
                            }
                        }
                    )
                }
                }
        }
    }
}

谢谢@Philip Dukhov

我之前尝试过这样做,但根本无法获得 item.Number、item.description、item.inventory(val 未解决)所以使用了 inventoryList,因为我可以得到根据您的建议,它至少是错误的方法。

我在过去几天的挣扎中学到了一两件事,所以有了你的提示,我设法实现了我需要的东西。不确定这是正确的方法,但它现在有效。继续下一场奋斗!

//***Modified the selected Item from val selectedItem = remember{ mutableStateOf(randomList[0])} to separate 3:


val selectedItemNumber = remember{ mutableStateOf(randomList[0])}
            
val selectedItemDescription = remember{ mutableStateOf(randomList[0])}
            
val selectedItemInventory = remember{ mutableStateOf(randomList[0])}


 LazyColumn(
                                    verticalArrangement = Arrangement.spacedBy(8.dp),
                                    modifier = Modifier
                                        .fillMaxSize()
                                        .padding(16.dp)
                                ) {

                                    itemsIndexed(inventoryList) { idx, item ->
                                        item.currentInventory?.let {
                                            MainScreenItemRow(
                                                itemNumber = item.itemNumber,
                                                itemDescription = item.itemDescription,
                                                currentInventory = it,
                                                onclick = {
                                                    selectedItemNumber.value = item.itemNumber
                                                    selectedItemDescription.value = item.itemDescription
                                                    selectedItemInventory.value = item.currentInventory.toString()
                                                    Log.d("MainActivityItemClicked", "$selectedItemDescription ")
                                                    showItemDialog.value = true

                                                }
                                            )
                                        }
                                    }


                                }
                                if (showItemDialog.value) {

                                                ItemAlertDialog(
                                                    itemNumber = selectedItemNumber.value,
                                                    itemDescription = selectedItemDescription.value,
                                                    currentInventory = selectedItemInventory.value.toInt(),
                                                    onDismiss = {
                                                        showItemDialog.value = !showItemDialog.value
                                                        Toast.makeText(
                                                            this@MainActivity,
                                                            "Dialog dismissed!",
                                                            Toast.LENGTH_SHORT
                                                        )
                                                            .show()
                                                    },
                                                    onNegativeClick = {
                                                        showItemDialog.value = !showItemDialog.value
                                                        Toast.makeText(
                                                            this@MainActivity,
                                                            "Cancel!",
                                                            Toast.LENGTH_SHORT
                                                        )
                                                            .show()

                                                    },
                                                    onPositiveClick = {
                                                        showItemDialog.value = !showItemDialog.value
                                                        Toast.makeText(
                                                            this@MainActivity,
                                                            "Saved!",
                                                            Toast.LENGTH_SHORT
                                                        )
                                                            .show()
                                                    }
                                                )


                                        }
                                    }