从 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
}
}
}
过去几天我一直在尝试使用新的 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
}
}
}