Reputation: 2276
In this answer I got wrong ripple animation. Do you know how to create ripple with rounded corners using Jetpack Compose?
With default ripple I have this:
Code:
Card(shape = RoundedCornerShape(30.dp),
border = BorderStroke(width = 2.dp, color = buttonColor(LocalContext.current)),
backgroundColor = backColor(LocalContext.current),
modifier = Modifier
.fillMaxWidth()
.padding(10.dp)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(radius = 30.dp)
) { show = !show }
) { ... } //Show is animation of other element.
//If I put radius of ripple 200 dp(it's a height of card) ripple works not normal.
Upvotes: 65
Views: 28910
Reputation: 685
In Material 3 1.5.0 or above You can do something like this.
modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.primaryContainer,
MaterialTheme.shapes.medium)
.clip(MaterialTheme.shapes.medium)
.clickable { onClickOfNewsITem(article.url ?: "") }
Just make sure you apply clip
property before onClick
. In Compose the order of property matters. because compose draw Ui in a top-to-bottom approach.
Read details - The three phases of a frame
Upvotes: 5
Reputation: 1732
Hope this will grant you the easiest solution
Just add .clip(RoundedCornerShape(30.dp)) in the modifier parameter
Here is the full code :
Card(modifier = Modifier
.padding(30.dp)
.size(100.dp)
.clip(RoundedCornerShape(30.dp))
.clickable {
// After clip //
}) { }
Upvotes: 15
Reputation: 245
using rememberRipple(bounded = false)
will give a circular ripple effect around the clicked component. It can be used as ->
Modifier.clickable(
indication = rememberRipple(bounded = false),
interactionSource = remember {
MutableInteractionSource()
}
) { }
Upvotes: 5
Reputation: 363379
Starting with M2 1.0.0-beta08
you can solve this issue using the onClick
lambda parameter in the Card
instead of the clickable
modifier:
Card(
shape = RoundedCornerShape(30.dp),
modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
onClick = { show = !show }
){
//card content
}
If you need the clickable
or the combinedClickable
modifier you have to use the variant without the onClick
parameter and to apply also the clip
modifier to the Card
using the same Card
shape:
val shape = RoundedCornerShape(30.dp)
Card(
shape = shape,
modifier = Modifier
//...height, width, padding
.clip(shape)
.combinedClickable(
onLongClick = { /** do something */ },
onClick = { /** do something */ }
)
){
//card content
}
With M3 Card
you can do the same.
Until 1.0.0-beta07
applying a .clickable
modifier to the Card
the ripples aren't clipped by the bounds of the layout.
As workaround you can apply the .clickable
modifier to the content of the Card (for example a Box
):
Card(
shape = RoundedCornerShape(30.dp),
border = BorderStroke(width = 2.dp, color = Color.Blue),
backgroundColor = Color.White,
modifier = Modifier
.fillMaxWidth()
.padding(10.dp)
) {
Box(Modifier
.clickable(
onClick = { /* ...*/ }
)
){
Text("Text")
}
}
Upvotes: 79
Reputation: 301
I checked the sources of Card/Surface composables and found out that you need to have background and clip modifiers with the same shape. So for example the following Box has rounded corner shape and click ripple is cut with the same bounds:
val shape = RoundedCornerShape(16.dp)
Box(
modifier = Modifier
.background(
color = Color.Yellow,
shape = shape
)
.clip(shape)
.clickable { onClick() },
) {
// your content here
}
Upvotes: 20
Reputation: 41
When you use long press or other gesture,you can use modifier.indication
val interactionSource = remember { MutableInteractionSource() }
Card(
modifier = Modifier
.padding(12.dp, 6.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
.indication(interactionSource, LocalIndication.current)
.pointerInput(Unit) {
detectTapGestures(
onPress = { offset ->
val press = PressInteraction.Press(offset)
interactionSource.emit(press)
tryAwaitRelease()
interactionSource.emit(PressInteraction.Release(press))
},
onLongPress = {},
onTap = {}
)
}
)
Upvotes: 0
Reputation: 2248
I've so far identified 2 options:
.clip
modifier to clip the Card using the same shape:Card(
shape = RoundedCornerShape(30.dp),
modifier = Modifier
.clip(RoundedCornerShape(30.dp))
.clickable {
//do something
}
) {
Box {
Text("Text")
}
}
The downside of this approach is that the elevation shadow gets clips as well, so your Card loses it's shadow.
.clickable
on the Card content composable: Card(
shape = RoundedCornerShape(30.dp)
) {
Box(
modifier = Modifier.clickable {
//do something
}
) {
Text("Text")
}
}
Upvotes: 42