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()
}
)
}
}
我正在做一个简单的项目,在这个项目中我导入了一个有空间的库存项目数据库,并且可以根据变化修改库存。我正在与 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()
}
)
}
}