[英]How to correctly upload image to an item in LazyList in Jetpack Compose?
我想讓用戶將圖像添加到 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 重新組合可見項目和將在滾動方向可見的項目,這是不可能,因為您沒有將它們保存在重組之外的某個地方(例如視圖模型)!
您可以將 Uris 或 Uris 作為字符串存儲在數據 class 中,例如
@Immutable
data class MyModel(
val title: String,
val description: String,
val uri: Uri? = null
)
並創建一個包含項目的 ViewModel 和一個 function 以在設置時更新 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)
}
)
}
}
}
結果
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.