android 线圈记忆AsyncImagePainter状态未更新

t5zmwmid  于 2022-12-09  发布在  Android
关注(0)|答案(3)|浏览(162)

我将CoilCompose沿着使用。
我试着在加载图像时制作一个 Flink 的动画。
所有示例都将ImagePainterImagePainter.State一起使用,它工作正常,但现在标记为“deprecated”。
这就是我选择AsyncImagePainter的原因。如果没有状态检查,它工作得很完美,但是有了检查,我得到了一个无限 Flink 的动画
我还尝试在AsyncImagePainter的onSuccess方法中使用mutableState更改加载状态var,但动画仍然无限

@Composable
fun FoodItem(food: Fun) {
    Column (
        modifier = Modifier.fillMaxWidth(),
        horizontalAlignment = Alignment.Start,
        verticalArrangement = Arrangement.Top
    ) {
        val painter = rememberAsyncImagePainter(food.image.sm)
        if (painter.state is AsyncImagePainter.State.Loading) {
            AnimatedShimmer { ShimmerFoodItem(brush = it) }
        } else {
            Image(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(104.dp)
                    .clip(RoundedCornerShape(size = 8.dp)),
                painter = painter,
                contentScale = ContentScale.Crop,
                contentDescription = "Food photo"
            )
            Text(
                modifier = Modifier.padding(top = 4.dp),
                text = food.title,
                fontSize = MaterialTheme.typography.body1.fontSize,
                overflow = TextOverflow.Ellipsis,
                maxLines = 1,
                fontWeight = FontWeight.Bold
            )
            Text(
                text = food.subtitle,
                fontSize = MaterialTheme.typography.subtitle2.fontSize,
                overflow = TextOverflow.Ellipsis,
                maxLines = 2,
                fontWeight = FontWeight.Normal
            )
        }
    }
}
vuv7lop3

vuv7lop31#

看起来painter需要立即提供给Image可组合对象,以便其状态可以更改,我尝试实现您的用例,并记录了painter.state,它不会得到更新,除非它立即提供给Image,所以我最终得到了以下结果

// random public image
val painter = rememberAsyncImagePainter(
    model = ImageRequest.Builder(LocalContext.current)
        .data("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUJ0jVyT2UJwn_Ln5s4yd17MtwLlgzm8-WTGKExqZg&s")
        .build()
)

Box {

    Image(
        modifier = Modifier.size(150.dp),
        painter = painter,
        contentDescription = ""
    )

    runBlocking {
        delay(500)
    }

    if (painter.state is AsyncImagePainter.State.Loading) {
        Box(
            modifier = Modifier
                .size(150.dp)
                .background(Color.Red)
        )
    }
}

基于Coil样本
请不要介意runbBlocking和红色的Box,我只是把它们放在那里模仿Image上面的东西( Flink ),并延迟显示实际的Image(获取)。希望这能有所帮助。

yzxexxkh

yzxexxkh2#

我是这样做的,当状态出错时,比如说,如果图像URL无效,就会显示一个保持器图标。但我添加了另一个状态showImage,它最初为true,并且可以在ImageLoadingState更改时更改。您可以将整个代码 Package 在一个函数中,该函数接受URL参数,并且根据ShowImage/Loading/Error的状态只显示一个Composable:

val modifier = Modifier
            .clip(RoundedCornerShape(CornerSize(10.dp)))
            .padding(4.dp)

val url = "your_image_url_or_not"

val imagePainter = rememberAsyncImagePainter(
    model = ImageRequest.Builder(LocalContext.current)
      .data(url)
      .crossfade(true)
      .build(),
  )

val showImage = remember {
    mutableStateOf(true)
  }
 if (showImage.value) {
    Image(
      painter = imagePainter,
      contentDescription = description,
      contentScale = ContentScale.Fit,
      modifier = modifier.padding(3.dp),
    )
  }

  if (imagePainter.state is AsyncImagePainter.State.Loading) {
    showImage.value = false
    CircularProgressIndicator(
      modifier = modifier,
      strokeWidth = 2.dp,
      color = MaterialTheme.colors.primaryVariant
    )
  } else if (imagePainter.state is AsyncImagePainter.State.Error) {
    showImage.value = false
    Icon(
      imageVector = Icons.Default.Person,
      contentDescription = description,
      modifier = modifier,
      tint = MaterialTheme.colors.primary
    )
  } else {
    showImage.value = true
  }
wpx232ag

wpx232ag3#

您需要使用

model = ImageRequest.Builder(LocalContext.current)
    .data(overlayImage)
    .size(coil.size.Size.ORIGINAL) // Set the target size to load the image at.
    .build()

如果您注解行大小为,您将看到它在加载状态时卡住。您还可以提供任何您希望加载图像的尺寸,例如1280x720和.size(coil.size.Size(1280, 720))

@Composable
private fun CoilSample() {
    val overlayImage =
        "https://images6.alphacoders.com/488/thumb-1920-488158.jpg"

    val painter = rememberAsyncImagePainter(
        model = ImageRequest.Builder(LocalContext.current)
            .data(overlayImage)
            .size(coil.size.Size.ORIGINAL) // Set the target size to load the image at.
            .build()
    )

    Column(modifier = Modifier.fillMaxSize()) {

        Text("state:${painter.state}")

        Box(
            modifier = Modifier.fillMaxSize(),
            contentAlignment = Alignment.Center
        ) {
            if (painter.state is AsyncImagePainter.State.Loading) {
                CircularProgressIndicator()
            } else {
                Image(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(104.dp)
                        .clip(RoundedCornerShape(size = 8.dp)),
                    painter = painter,
                    contentScale = ContentScale.Crop,
                    contentDescription = "photo"
                )
            }
        }
    }
}

如果您需要从Coil的Painter获得BitmapImageBitmap,也可以查看此答案
在可组合文件中使用之前获取位图

相关问题