从 LazyColumn 导航到 AlertDialog

Navigate to AlertDialog from LazyColumn

过去几天我一直在尝试使用新的 Jetpack Compose,它非常棒,但现在我被困在了一些应该非常简单的事情上。我想要做的就是在用户单击(或长按)列表中的项目并将单击的项目作为参数传递给 AlertDialog 时,从 LazyColumn (RecyclerView) 显示一个 AlertDialog。我已经设法在不传递任何参数的情况下做到这一点,并且只显示带有预设信息的 AlertDialog。它也可以很好地显示带有单击项目的 Toast 消息。这是我的代码(它与 GitHub 上的 compose-samples 中的 Rally 应用程序基本相同):

@ExperimentalFoundationApi
@Composable
fun AccountsBody(navController: NavController, viewModel: AccountsViewModel) {

    val accountsFromVM = viewModel.accounts.observeAsState()

    accountsFromVM.value?.let { accounts ->
        StatementBody(
            items = accounts, // this is important for the question
            // NOT IMPORTANT
            amounts = { account -> account.balance },
            colors = { account -> HexToColor.getColor(account.colorHEX) },
            amountsTotal = accounts.map { account -> account.balance }.sum(),
            circleLabel = stringResource(R.string.total),
            buttonLabel = DialogScreen.NewAccount.route,
            navController = navController,

            onLongPress = {  } // show alert
        ) { account, _ -> // this is important for the question
            AccountRow(
                name = account.name,
                bank = account.bank,
                amount = account.balance,
                color = HexToColor.getColor(account.colorHEX),
                account = account,
                onClick = { },
                onlongPress = { clickedItem ->
                    // Show alert dialog here and pass in clickedItem
                }
            )
        }
    }
}
@Composable
fun <T> StatementBody(
    items: List<T>,
    // NOT IMPORTANT
    colors: (T) -> Color,
    amounts: (T) -> Float,
    amountsTotal: Float,
    circleLabel: String,
    buttonLabel: String,
    navController: NavController,

    onLongPress: (T) -> Unit,
    rows: @Composable (T, (T) -> Unit) -> Unit
) {
    Column {
        // Animating circle and balance box
        // NOT IMPORTANT - (see last few rows for the important part)
        Box(Modifier.padding(16.dp)) {
            val accountsProportion = items.extractProportions { amounts(it).absoluteValue }
            val circleColors = items.map { colors(it) }
            AnimatedCircle(
                accountsProportion,
                circleColors,
                Modifier
                    .height(300.dp)
                    .align(Alignment.Center)
                    .fillMaxWidth()
            )
            Column(modifier = Modifier.align(Alignment.Center)) {
                Text(
                    text = circleLabel,
                    style = MaterialTheme.typography.body1,
                    modifier = Modifier.align(Alignment.CenterHorizontally)
                )
                Text(
                    text = formatAmount(amountsTotal),
                    style = MaterialTheme.typography.h2,
                    modifier = Modifier.align(Alignment.CenterHorizontally)
                )
                Button(onClick = { navController.navigate("${buttonLabel}/Nytt sparkonto") }) {
                    Text(text = buttonLabel)
                }
            }
        }
        Spacer(Modifier.height(10.dp))

        // Recycler view
        // THIS IS THE IMPORTANT PART
        Card {
            LazyColumn(modifier = Modifier.padding(12.dp)) {
                itemsIndexed(items) { idx, item ->
                    rows(item, onLongPress)  // rows is the Composable you pass in
                }
            }
        }

    }
}
@ExperimentalFoundationApi
@Composable
fun AccountRow(
    name: String,
    bank: String,
    amount: Float,
    color: Color,
    account: AccountData,
    onClick: () -> Unit,
    onlongPress: (AccountData) -> Unit
) {
    BaseRow(
        color = color,
        title = name,
        subtitle = bank,
        amount = amount,
        rowType = account,
        onClick = onClick,
        onLongPress = onlongPress
    )
}

@ExperimentalFoundationApi
@Composable
private fun <T> BaseRow(
    color: Color,
    title: String,
    subtitle: String,
    amount: Float,
    rowType: T,
    onClick: () -> Unit,
    onLongPress: (T) -> Unit
) {
    val formattedAmount = formatAmount(amount)
    Row(
        modifier = Modifier
            .height(68.dp)
            .combinedClickable(
                onClick = onClick,
                onLongClick = { onLongPress(rowType) }  //HERE IS THE IMPORTANT PART
            ),
        verticalAlignment = Alignment.CenterVertically
    ) {
        val typography = MaterialTheme.typography

        AccountIndicator(color = color, modifier = Modifier)
        Spacer(Modifier.width(12.dp))

        Column(Modifier) {
            Text(text = title, style = typography.body1)
            CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
                Text(text = subtitle, style = typography.subtitle1)
            }
        }

        Spacer(Modifier.weight(1f))

        Row(horizontalArrangement = Arrangement.SpaceBetween) {
            Text(
                text = "$formattedAmount kr",
                style = typography.h6,
                modifier = Modifier.align(Alignment.CenterVertically)
            )
        }

        Spacer(Modifier.width(16.dp))

    }
    RallyDivider()
}

如能提供有关如何实现此目的的任何帮助,我们将不胜感激。总的来说,我对 android 开发和编程有点陌生,所以我可能已经把它变得比它必须的更复杂了。

这可以通过将所选项目保存为 MutableState 来轻松完成,是否显示对话框是另一个 MutableState

这是可以作为起点的简化示例:

    val items = emptyList<String>()
    val currentSelectedItem = remember{ mutableStateOf(items[0]) }
    val showDialog = remember{ mutableStateOf(false) }

     //ShowDialogis is ur composable fun that takes the clicked item
    if(showDialog.value) ShowDialog(currentSelectedItem.value) 

    Card {
        LazyColumn(modifier = Modifier.padding(12.dp)) {
            itemsIndexed(items) { idx, item ->
                Row( )  {
                    Text(text = item,Modifier.clickable { 
                        currentSelectedItem.value = item
                        showDialog.value=true
                    })
                }// rows is the Composable you pass in
            }
        }
    }