【问题标题】:Conditionally show image from the gallery or drawable resource using Coil and Jetpack Compose使用 Coil 和 Jetpack Compose 有条件地显示来自画廊或可绘制资源的图像
【发布时间】:2021-08-09 14:10:16
【问题描述】:

如果用户选择了任何内容,我会尝试从图库中显示图像,或者将可绘制资源中的图像文件中的图像显示为默认图像,但这不起作用。我正在使用 Coil for Compose 并已经添加了依赖项。代码如下:

class MainActivity : ComponentActivity() {
    private var imageUriState = mutableStateOf<Uri?>(null)

    private val selectImageLauncher = registerForActivityResult(GetContent()) { uri ->
        imageUriState.value = uri
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ImageSourceActivityScreen()
        }
    }

    @Composable
    fun ImageSourceActivityScreen() {
        Column(
            modifier = Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center
        ) {
            Image(
                painter = rememberImagePainter(
                    if (imageUriState != null) {
                        imageUriState.value
                    } else {
                        R.drawable.blank_profile_picture
                    }
                ),
                contentDescription = "profile image",
                contentScale = ContentScale.Crop,
                modifier = Modifier.fillMaxWidth()
            )
    ...
}

没有显示错误,但也没有显示默认图像。请帮助使其工作。谢谢!

【问题讨论】:

  • 用户选择的图像是否有效?你用的是哪个版本的compose和coil?
  • 什么都没有显示 - 甚至是 UI 的其余部分(按钮)!现在修好了,谢谢!

标签: android kotlin android-jetpack-compose coil


【解决方案1】:

您的代码不起作用,因为您将 imageUriStatenull 进行比较,这始终是正确的

你有两个选择:

  1. 根据您的状态值指定画家
Image(
    painter = if (imageUriState.value != null) {
        rememberImagePainter(
            imageUriState.value
        )
    } else {
        painterResource(id = R.drawable.blank_profile_picture)
    },
    contentDescription = "profile image",
    contentScale = ContentScale.Crop,
    modifier = Modifier.fillMaxWidth()
)
  1. 默认情况下,如果您将null 作为数据传递,则线圈不会显示占位符,这通常是有意义的。如果您想在没有图像时和等待图像加载时都看到占位符,您可以创建这样的函数:
@Composable
inline fun rememberImagePainter(
    data: Any?,
    @DrawableRes emptyPlaceholder: Int,
    builder: ImageRequest.Builder.() -> Unit = {},
): Painter {
    val painter = rememberImagePainter(
        data,
        builder = {
            placeholder(emptyPlaceholder)
            builder()
        }
    )
    if (data == null) {
        return painterResource(emptyPlaceholder)
    }
    return painter
}

// usage
Image(
    painter = rememberImagePainter(
        "https://i.stack.imgur.com/rkyep.jpg",
        emptyPlaceholder = R.drawable.test,
    ),
    contentDescription = "profile image",
    contentScale = ContentScale.Crop,
    modifier = Modifier.fillMaxSize()
)

【讨论】:

  • 得到了在哪里寻找错误并找到它的提示!我在没有 .value 的情况下调用 imageUriState。解决了这个问题,它现在可以工作了!感谢您的回答!
  • 我尝试了第二种解决方案,但由于某种奇怪的原因它不起作用!甚至 UI 的其余部分都不像我的代码那样显示!
  • 尝试了第一个解决方案,在 if 逻辑中添加了 .value 部分,它有效。感谢您展示推荐的方式!您能否检查一下为什么第二种解决方案不起作用?
  • 我已经重新检查了第二种情况,它似乎很好,如果没有看到完整的代码,就不能说在你的情况下到底是什么不起作用
  • 你能看看这里的代码吗:github.com/rawhasan/compose-exercises-image-source
【解决方案2】:

可以使用builder参数设置placeholder

val painter = rememberImagePainter(
    imageUriState.value,
    builder = {
        placeholder(R.drawable.blank_profile_picture)
    }
)
Image(
    painter,
    contentDescription = "profile image",
    contentScale = ContentScale.Crop,
    modifier = Modifier.fillMaxWidth()
)

【讨论】:

  • 得到了在哪里寻找错误并找到它的提示!我打电话给imageUriState,没有.value。解决了这个问题,它现在可以工作了!再次感谢!!
【解决方案3】:

从@Gabriele Mariotti 的回答中找到了在哪里寻找错误的提示。我打电话给imageUriState,没有.value。解决了这个问题,它现在正在工作。谢谢大家的帮助!

Image(
    painter = rememberImagePainter(
        if (imageUriState.value != null) {
            imageUriState.value
        } else {
            R.drawable.blank_profile_picture
        }
    ),
    contentDescription = "profile image",
    contentScale = ContentScale.Crop,
    modifier = Modifier.fillMaxWidth()
)

【讨论】:

    猜你喜欢
    • 2011-09-14
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多