android - 使用 Jetpack Compose for Android 动画形状

标签 android android-animation android-jetpack-compose

我想像这样使用像普通 Android 12 这样的组合来构建一个很棒的锁屏:

我设法做了类似的事情,但是我有 2 个问题,一个是当我使用 pointerInteropFilter 获取 Action 事件时我使用 remember 值来改变形状,在这个函数中返回 true 我得到了一个类似的动画,但是没有调用点击监听器,如果我返回 false 形状保持在“正方形”,我错过了什么?有什么方法可以使“形状”动画化?我找到了 DP、颜色和尺寸,但没有找到形状。 这是代码

@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()
        }
    }
}

这是我的结果

<表类="s-表"> <头> 语法 描述 <正文> 运动事件为真 运动事件假 Motion event returns true but no ripple or click Motion event returns false but stays in square shape

最佳答案

为了设置半径动画,您需要使用 animate*AsState() API 之一。

这里的关键是通过使用 animateDpAsState() 逐渐改变 Shape 的角半径,因为 Circle 是 RoundedCornerShape,角半径是整个Circle的大小。

为了获得涟漪,您可以使用带有 rememberRipple() 作为指示的可点击修饰符。

下面是两者的一个工作示例:

@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()
        }
    }
}

Animation with radius and ripple

关于android - 使用 Jetpack Compose for Android 动画形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72009932/

相关文章:

android - 如何使用 ADB 查看受监控的地理围栏列表?

android - 我如何将行内的小部件居中?

android - 如何动态获取/res/raw中的所有媒体文件?

android - 用于创建 AnimatedVectorDrawable 的工具

android - animation.start() 或 animation.startNow() 不会立即启动动画

java - oncreate()中可以播放soundPool吗?

Android 幻灯片元素删除

安卓撰写。尝试运行基本代码时出错

android - 嵌套滚动 Jetpack Compose

android - 为什么jetpack compose海拔会夹住我的影子?