I want to build a great lockscreen using compose like stock Android 12 like this:

I managed to do something similar, however i have 2 issues, one is when I use pointerInteropFilter to get the action events I use a remember value to change the shape, returning true in this function I got a similar animation, however the click listener is not called, if I return false the shape stays in "square", What I'm missing? is any way to animate the "shape"? I found for DP, color and size but not for shapes.
here is the code
@Composable
fun RoundedPinBackground(
modifier: Modifier = Modifier,
backgroundColor: Color,
onClicked: () -> Unit,
content: @Composable () -> Unit,
) {
var selected by remember { mutableStateOf(false) }
val shape = if (selected) {
RoundedCornerShape(10.dp)
} else {
CircleShape
}
Surface(
tonalElevation = 10.dp,
modifier = Modifier
.clip(shape)
) {
Box(modifier = modifier
.size(80.dp)
.clip(shape)
.background(color = backgroundColor)
.clickable { onClicked.invoke() }
.pointerInteropFilter {
when (it.action) {
MotionEvent.ACTION_DOWN -> {
selected = true
}
MotionEvent.ACTION_UP -> {
selected = false
}
}
true
},
contentAlignment = Alignment.Center
) {
content()
}
}
}
This are my results
| Syntax | Description |
|---|---|
| Motion event true | Motion event false |
![]() |
![]() |
In order to animate the radius you need to use one of the animate*AsState() APIs.
They key here would be to change the corner radius of your Shape progressively by using animateDpAsState(), as a Circle is a RoundedCornerShape with the corner radius as half the size of the overall Circle.
In order to get the ripple, you can use the clickable modifier with rememberRipple() as the indication.
Below is a working example of both:
@Composable
fun RoundedPinBackground(
modifier: Modifier = Modifier,
size: Dp,
backgroundColor: Color,
onClicked: () -> Unit,
content: @Composable () -> Unit,
) {
val interactionSource = remember { MutableInteractionSource() }
val isPressed = interactionSource.collectIsPressedAsState()
val radius = if (isPressed.value) {
10.dp
} else {
size / 2f
}
val cornerRadius = animateDpAsState(targetValue = radius)
Surface(
tonalElevation = 10.dp,
modifier = modifier
.clip(RoundedCornerShape(cornerRadius.value))
) {
Box(
modifier = Modifier
.background(color = backgroundColor)
.size(size)
.clip(RoundedCornerShape(cornerRadius.value))
.clickable(
interactionSource = interactionSource,
indication = rememberRipple()
) { onClicked.invoke() },
contentAlignment = Alignment.Center
) {
content()
}
}
}

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With