Reputation: 1685
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
Upvotes: 6
Views: 5013
Reputation: 2982
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()
}
}
}
Upvotes: 11