我想让用户将图像添加到 LazyColumn 中的每个项目(卡片)。但似乎图像在重组时被删除了。我该如何解决?
@Composable
fun PhotoUpload(
) {
val imageUri = remember {
mutableStateOf<Uri?>(null)
}
val context = LocalContext.current
val bitmap = remember {
mutableStateOf<Bitmap?>(null)
}
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.GetContent()
) { uri: Uri? ->
imageUri.value = uri
}
imageUri.value?.let {
LaunchedEffect(Unit) {
if (Build.VERSION.SDK_INT < 28) {
bitmap.value = MediaStore.Images
.Media.getBitmap(context.contentResolver, it)
} else {
val source = ImageDecoder
.createSource(context.contentResolver, it)
bitmap.value = ImageDecoder.decodeBitmap(source)
}
}
}
bitmap.value?.let { btm ->
Image(
bitmap = btm.asImageBitmap(),
contentDescription = null,
modifier = Modifier.size(400.dp)
)
}
Button(onClick = {
launcher.launch("image/*")
}) {
Icon(Icons.Filled.PhotoAlbum, "")
}
}
图片被删除(他们不会回来,这是一个循环 gif)
PS:对于 LazyColumn,我确实使用键。我也尝试使用 Coil 的 AsyncImage,但它有同样的问题
最佳答案
它被删除是因为当您从上传的图像滚动离开时,LazyColumn 删除不再可见的项目以获得更好的性能,LazyList 在引擎盖下使用 SubcomposeLayout 重新组合可见项目和将在滚动方向可见的项目,这是不可能的,因为您没有将它们保存在重组之外的某个地方(例如 View 模型)!
您可以将 Uris 或 Uris 作为字符串存储在数据类中,例如
@Immutable
data class MyModel(
val title: String,
val description: String,
val uri: Uri? = null
)
然后创建一个包含项目的 ViewModel 和一个在设置时更新 Uri 的函数
class MyViewModel : ViewModel() {
val items = mutableStateListOf<MyModel>()
.apply {
repeat(15) {
add(MyModel(title = "Title$it", description = "Description$it"))
}
}
fun update(index: Int, uri: Uri) {
val item = items[index].copy(uri = uri)
items[index] = item
}
}
通过点击按钮获取 Uri
@Composable
fun PhotoUpload(
onError: (() -> Unit)? = null,
onImageSelected: (Uri) -> Unit
) {
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.GetContent()
) { uri: Uri? ->
if (uri == null) {
onError?.invoke()
} else {
onImageSelected(uri)
}
}
Button(onClick = {
launcher.launch("image/*")
}) {
Icon(Icons.Filled.PhotoAlbum, "")
}
}
设置后通过回调返回Uri的行
@Composable
private fun MyRow(
title: String,
description: String,
uri: Uri?,
onImageSelected: (Uri) -> Unit
) {
Column(
modifier = Modifier
.shadow(ambientColor = Color.LightGray, elevation = 4.dp)
.fillMaxWidth()
.background(Color.White, RoundedCornerShape(8.dp))
.padding(8.dp)
) {
Text(title)
Text(description)
uri?.let { imageUri ->
AsyncImage(
modifier = Modifier
.fillMaxWidth()
.aspectRatio(4 / 3f),
model = imageUri, contentDescription = null
)
}
PhotoUpload(onImageSelected = onImageSelected)
}
}
用法
@Composable
private fun ImageUploadSample(viewModel: MyViewModel) {
LazyColumn {
itemsIndexed(
key = { _, item ->
item.hashCode()
},
items = viewModel.items
) { index, myModel ->
MyRow(
title = myModel.title,
description = myModel.description,
uri = myModel.uri,
onImageSelected = { uri ->
viewModel.update(index, uri)
}
)
}
}
}
结果
关于android - 如何正确地将图像上传到 Jetpack Compose 中的 LazyList 中的项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74678368/