如何在Jetpack Compose中将可绘制对象设置为图像的背景?

23
如何在Jetpack Compose中将可绘资源设置为Image的背景?对应的视图XML代码是什么?

Corresponding view XML code

对应的视图XML代码
<androidx.appcompat.widget.AppCompatImageView
    android:background="@drawable/drawable_black_circle"
    android:src="@drawable/app_logo"
    ... 
/>

我的当前代码,

Image(
    painter = painterResource(id = R.drawable.app_logo),
    contentDescription = null,
    modifier = Modifier
        .height(160.dp)
        .width(160.dp)
        .padding(32.dp),
)

Modifier.background()让我可以将颜色用作背景。
类似地,我正在寻找一种使用可绘制资源作为背景的方法。

注意:
我正在寻找一种将图像用作背景的方法。
不要求将图像包含在具有背景的另一个组件中。


drawable_black_circle是什么?也许在Compose中有另一种方法。你能发布最终AppCompatImageView的屏幕截图吗? - Gabriele Mariotti
@GabrieleMariotti,这只是一个样例drawable。我正在尝试查找是否存在一个可接受源drawable和背景drawable的组合件。我知道可以创建自定义drawable来实现此功能。 - Abhimanyu
没有,但是有很多方法可以实现相同的目标。 - Gabriele Mariotti
4个回答

30
在Jetpack Compose中设置背景图片
fun MainViews(){
  Box(
    modifier = with (Modifier){
      fillMaxSize()
        .paint(
           // Replace with your image id 
           painterResource(id = R.drawable.image),
           contentScale = ContentScale.FillBounds) 

})
{
  // Add more views here!
  Text("Hello Stack!")
}}


注意:我是在我的安卓手机上编写这段代码的,可能会有一些语法错误。

2
我实际上会推荐这个。 - Jan Ndungu
1
完全同意。这是当前日期的正确答案。 - bmoss
请使用"ContentScale.FillBounds"而不是"ContentScale.fillBounds"。 - undefined
完美地工作。 - undefined

17

使用Jetpack Compose,通过使用形状来轻松绘制圆形背景或任何形状。

解决方案1:

Image(painterResource(id = R.drawable.avatar1), contentDescription = null,
        modifier = Modifier.size(160.dp).background(
            color = Color.Black,
            shape = CircleShape
        )
            )

解决方案2:如果您想使用背景图片,您可以使用:

Modifier.paint

对于您的情况:

Image(
    painter = painterResource(id = R.drawable.app_logo),
    contentDescription = null,
    modifier = Modifier
        .height(160.dp)
        .width(160.dp)
        .paint(
            painter = painterResource(R.drawable.drawable_black_circle),
            contentScale = ContentScale.FillWidth
        )
        .padding(32.dp),
)

对于其他布局,我们可以做同样的事情。以下是ConstraintLayout的示例

ConstraintLayout(
        modifier = Modifier
            .fillMaxWidth()
            .paint(painterResource(id = R.drawable.ic_background_detail), contentScale = ContentScale.FillWidth)
    ) {

    }
  

8

您可以将两个图像放在一个Box中,这样主要的图像就会位于背景之上。

如果您要广泛使用这样的视图,可以创建自己的可组合项,只需像这样简单地使用:

ImageWithBackground(
    painter = painterResource(id = R.drawable.app_logo),
    backgroundDrawableResId = R.drawable.background,
    contentDescription = "",
    modifier = Modifier
        .height(160.dp)
        .width(160.dp)
        .padding(32.dp),
)

可组合的:

@Composable
fun ImageWithBackground(
    painter: Painter,
    @DrawableRes backgroundDrawableResId: Int,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    alignment: Alignment = Alignment.Center,
    contentScale: ContentScale = ContentScale.Fit,
    alpha: Float = DefaultAlpha,
    colorFilter: ColorFilter? = null
) {
    Box(
        modifier = modifier
    ) {
        Image(
            painter = painterResource(backgroundDrawableResId),
            contentDescription = null,
            modifier = Modifier
                .matchParentSize()
        )
        Image(
            painter = painter,
            contentDescription = contentDescription,
            alignment = alignment,
            contentScale = contentScale,
            alpha = alpha,
            colorFilter = colorFilter,
            modifier = Modifier
                .matchParentSize()
        )
    }
}

感谢您的回答。我已经知道这种方法了。正如问题中所提到的,“不想将图像与背景封装在另一个组合中。” 我正在尝试使用单个组合来实现这一点。对于这样一个简单的需求,使用一个Box和两个Images似乎需要太多的代码,而在Views中,这个需求显然有一个简单的代码。 附言:drawable名称只是举例而已。 - Abhimanyu
@Abhimanyu 我明白了。没有内置的解决方案,但请查看更新的答案,了解如何在您的应用程序中轻松使用它。 - Phil Dukhov

1
先生,如果您绝对不希望将图像嵌套在另一个图像中,您可以使用Canvas构建它。然而,在底层,这就是它的本质——一个图像覆盖在另一个图像上。一个Box只是一个定位机制。如果您决定使用Canvas,这就是如何使用它的方法:
val backgroundVector = ImageVector.vectorResource(id = R.drawable.ic_launcher_foreground)
val backgroundPainter = rememberVectorPainter(image = backgroundVector)

val foregroundVector = ... // Same as above
val foregroundPainter = rememberVectorPainter(...) // Same as above

Canvas(modifier = Modifier.fillMaxSize()) {
    with(backgroundPainter) {
        draw(painter.intrinsicSize) // You can scale and modify, all the good stuff
    }
    with(foregroundPainter) {
        // Ditto as above,
    }
}

还有可用的transform范围,或者单独的translaterotatescale,也许还有更多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接