In compose, I have an Image which can be either
not tinted
tinted with a color on top
have a background tint
I know how to do each of the state, what I don't know is how to combine 2+3 together: Have the background green color and the tint purple color.
My code (just the image), I omitted the label:
#Preview
#Composable
private fun imageWithTint(){
Image(
painterResource(id = R.drawable.oval),
contentDescription = "tint",
modifier = Modifier.size(30.dp).clip(CircleShape),
colorFilter = getColorFilter(Color.Green, Color.Blue)
)
}
private fun getColorFilter(backgroundIconColor: Color?, selectionColor: Color): ColorFilter {
// todo couldn't apply selectionColor together with backgroundIconColor, so gave backgroundIconColor priority
return when {
backgroundIconColor != null -> {
ColorFilter.tint(backgroundIconColor, blendMode = BlendMode.DstOver)
}
else -> ColorFilter.tint(selectionColor, blendMode = BlendMode.SrcIn)
}
}
You can create a backgroud color with a shape using Modifier.background(color, shape)
Image(
painter = painterResource(id = R.drawable.ic_baseline_check_circle_outline_24),
contentDescription = null,
modifier = Modifier.background(Color.Green, CircleShape).size(30.dp),
colorFilter = ColorFilter.tint(Color.Magenta)
)
This will create a green circle background with magenta tint
Related
I have such an implemenation
Surface(
modifier = Modifier.background(Color.Transparent),
shape = RoundedCornerShape(corner = CornerSize(2.dp)),
border = BorderStroke(width = 1.dp, color = showpageColorAgvotBoarder)
) {
Text(
modifier = Modifier.padding(2.dp),
text = item,
style = ShowpageAgvotStyle
)
}
the result I get is
Like entire background is black, however, surface backgroudn is white...
I need just a boarder and background of surface should be transparent (in this case black as entire background is black)
What am I doing wrong?
You need to use color = Color.Transparent parameter instead of Modifier.background(Color.Transparent)
Surface(
modifier = Modifier,
shape = RoundedCornerShape(corner = CornerSize(2.dp)),
border = BorderStroke(width = 1.dp, color = Color.Red),
color = Color.Transparent // This is what you're missing
) {
Text(
modifier = Modifier.padding(2.dp),
text = "item",
color = Color.Gray
)
}
Surface has a new color parameter that dictates the color instead of the modifier.
The background color of the Surface is based on the color attribute.
By default is:
MaterialTheme.colors.surface (M2)
MaterialTheme.colorScheme.surface (M3).
Use:
Surface(
color = Color.Transparent,
//..
) {
//...
}
This is not a duplicate of Modify ripple color of IconButton in Jetpack Compose This question was diverted in a different way...
I am trying to change the IconButton ripple colour as follows
IconButton(
modifier = modifier
.indication(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(
bounded = false,
radius = 30.dp,
color = colorResource(id = R.color.error_red)
)
)
.background(colorResource(id = R.color.white), shape = CircleShape),
onClick = { onButtonPressed() }
) {
Icon(
painter = painterResource(R.drawable.ic_busy_small_busy),
contentDescription = buttonContentDesc,
)
}
The ripple colour does not change. It stays dark Grey.
Also, Is there a way to change the alpha of the ripple??
I load the image by url using the coil library.
After loading I need to draw a border around the image depending of background color of uploaded picture.
For example, if I loaded the picture with white background, I need to set black border.
val painter =
rememberAsyncImagePainter(
ImageRequest.Builder(LocalContext.current)
.data(data = imageUrl)
.apply(block = fun ImageRequest.Builder.() {
crossfade(true)
allowHardware(false)
}).build()
)
val painterState = painter.state
Image(
painter = painter,
contentDescription = null,
modifier = Modifier
.padding(start = 20.dp, top = 20.dp)
.width(130.dp)
.height(68.dp)
)
When painter.state is Succes, i'm picking the color of loaded drawable with Palette library.
How can I access to image after successful loading and draw the border in needed color?
I assume you mean
by How can I access to image after successful
exact bounds of area is ImageBitmap drawn inside Image with ContentScale. If that's the issue i built a library that returns exact bounds and which section of image is drawn but since i'm not sure not adding sample with it. If you don't need exactly the bounds check the answer below
You can define a Color with var color by remember {mutableStateOf(Color.Unspecified)
Modifier.border(x.dp, color) will be recomposed when this color changes. After getting desired color from Palette Api if you set color = colorVibrant for instance, you will be able to draw border around your Image with correct dimensions.
State check here is for creating a producible sample
val painter =
rememberAsyncImagePainter(
ImageRequest.Builder(LocalContext.current)
.data(data = "https://source.unsplash.com/pGM4sjt_BdQ")
.apply(block = fun ImageRequest.Builder.() {
crossfade(true)
allowHardware(false)
}).build()
)
var color by remember { mutableStateOf(Color.Unspecified) }
val painterState = painter.state
if (painterState is AsyncImagePainter.State.Success) {
color = Color.Red
}
Column() {
Spacer(Modifier.height(50.dp))
Text("PainterState State: ${painterState.painter}")
Image(
painter = painter,
contentDescription = null,
modifier = Modifier
.padding(start = 20.dp, top = 20.dp)
.border(2.dp, color)
.width(300.dp)
.height(268.dp)
)
}
Android Jetpack compose Card draws a border around the card when background color has some transparency. This is how it looks in AS:
But this is how it looks in the app:
If I set background to a solid color it works, but by default backgroundColor is a surface color from material (in my app val white850 = Color(0xD9FFFFFF)) and it looks like on the picture above.
#Composable
fun TraitCard(trait: Trait) {
Card(
shape = MaterialTheme.shapes.small,
modifier = Modifier.size(width = 192.dp, height = 56.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Start
) {
Icon(
imageVector = Icons.Rounded.ChildFriendly,
contentDescription = "",
modifier = Modifier
.fillMaxHeight()
.background(color = MaterialTheme.colors.background)
.aspectRatio(1f)
.padding(8.dp),
tint = MaterialTheme.colors.onBackground
)
Text(
text = trait.name,
style = MaterialTheme.typography.h3,
modifier = Modifier.padding(horizontal = 16.dp),
)
}
}
}
Does anyone have a clue why it's happening?
This is because of the elevation that Card has by default (and how shadows are drawn), if you remove the elevation this won't happen.
You can try to convert the semitransparent color to the non transparent one with something like:
backgroundColor = Color(0xD9FFFFFF).compositeOver(Color.White),
I want to achieve this layout:
In XML I would add an image in a relative layout with match_parent attributes, then a view with a black half-transparent background set to match_parent as well, then the content.
In compose I made this composeable:
#Composable
fun ImageCover(resourceId: Int, alpha: Float = 0.5f, content: #Composable () -> Unit) {
Box(modifier = Modifier.fillMaxSize()) {
Image(
painter = painterResource(id = resourceId),
contentDescription = null,
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop
)
Surface(
color = Color.Black, modifier = Modifier
.fillMaxSize()
.alpha(alpha)
) {
content()
}
}
}
But the problem is alpha is applied to the surface and its content. So no matter what I put in the content, even if it's another surface with a background, will also be half transparent. Here, for example, the two sentences and two components at the bottom will be half transparent as well.
The background color of the Surface is based on the color attribute.
Apply the alpha to the color property instead of the Modifier.
Something like:
Surface(
color = Color.Black.copy(alpha = 0.6f),
modifier = Modifier.fillMaxSize()
){
//....
}