Issue
I am trying the change a button background from a solid color to a dawable image with transparent background to make sure I can see the pattern
I moved to jetpack so I have created
Button(onClick = { /*TODO*/ },
colors = ButtonDefaults.buttonColors(
backgroundColor = colorResource(id = R.color.gainsboro_00)),
modifier = Modifier
.fillMaxWidth()
.height(60.dp),
shape = RoundedCornerShape(0.dp)) {
Text(text = stringResource(id = R.string.login),
color = colorResource(id = R.color.gainsboro_05),
style = MaterialTheme.typography.body1)
}
This button has a grey background.
I would like to apply the drawable below:
<?xml version="1.0" encoding="UTF-8" ?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/pattern_stripe_loose_gainsboro_05"
android:tileMode="repeat"/>
as a background instead of the colored one and have the pattern displayed. the above xml is just repeating a pattern to create a background
So I expect this:
using the pattern:
When using the traditional way with layout and so on it works but I can't make it work on jetpack
Any idea ?
Solution
Compose does not have such a feature yet. You can create a feature request on issue tracker.
Before this is implemented, you could create a pure Compose solution that draws a lot of images, but I think there is no point in doing that when there is ImageView
already optimized by engineers. In such cases you can use AndroidView
for interop with old views.
@Composable
fun TileAndroidImage(
@DrawableRes drawableId: Int,
contentDescription: String,
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
val drawable = remember(drawableId) {
BitmapDrawable(
context.resources,
BitmapFactory.decodeResource(
context.resources,
drawableId
)
).apply {
tileModeX = Shader.TileMode.REPEAT
tileModeY = Shader.TileMode.REPEAT
}
}
AndroidView(
factory = {
ImageView(it)
},
update = { imageView ->
imageView.background = drawable
},
modifier = modifier
.semantics {
this.contentDescription = contentDescription
role = Role.Image
}
)
}
Next part, is puttin it in background of the button. In compose we use containers to do so. You can create your TiledButton
. I pass zero padding to container button and add real padding manually so it'll not affect the background:
@Composable
fun TiledButton(
onClick: () -> Unit,
@DrawableRes backgroundDrawableId: Int,
modifier: Modifier = Modifier,
enabled: Boolean = true,
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = null,
contentColor: Color = MaterialTheme.colors.primary,
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
content: @Composable RowScope.() -> Unit
) {
Button(
onClick = onClick,
contentPadding = PaddingValues(0.dp),
enabled = enabled,
shape = shape,
border = border,
elevation = null,
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Transparent,
contentColor = contentColor,
disabledBackgroundColor = Color.Transparent,
disabledContentColor = contentColor.copy(alpha = ContentAlpha.disabled),
),
modifier = modifier
) {
Box(
contentAlignment = Alignment.Center,
) {
TileAndroidImage(
drawableId = backgroundDrawableId,
contentDescription = "...",
modifier = Modifier.matchParentSize()
)
Row(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(contentPadding),
content = content,
)
}
}
}
Usage:
TiledButton(
onClick = { /*TODO*/ },
backgroundDrawableId = R.drawable.tile,
border = BorderStroke(1.dp, Color.Blue),
) {
Text("Apple")
}
Answered By - Philip Dukhov
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.