将列从Arrangement.Center动画到Arrangement.Top。

huangapple go评论59阅读模式
英文:

Animate Column from Arrangement.Center to Arrangement.Top

问题

我正在使用Jetpack Compose原生动画来创建一个包含一些步骤的复杂过渡效果。问题是,原始的Column的排列方式被设置为居中,而在列中添加一些元素后,排列方式需要切换到顶部。如果只是改变排列方式,我希望得到一个连续的效果,而不是目前的中断。

是否有办法来动画化这种属性?

致意。

英文:

I am using Jetpack Compose native animations to create a complex transition with some steps. The issue is that the original Column has the arrangement set to Center and after the inclusion of some elements in the column, the arrangement needs to switch to Top. If I just change the arrangement, I would like a continuous effect instead of the current break.

Is there any way to animate this kind of property?

Regards.

答案1

得分: 4

可以使用Modifier.onPlaced和Modifier.offset来实现这个效果,通过创建一个Modifier函数来实现:

fun Modifier.animatePlacement(): Modifier = composed {
    val scope = rememberCoroutineScope()
    var targetOffset by remember { mutableStateOf(IntOffset.Zero) }
    var animatable by remember {
        mutableStateOf<Animatable<IntOffset, AnimationVector2D>?>(null)
    }
    this
        // &#128293; onPlaced should be before offset Modifier
        .onPlaced {
            // Calculate the position in the parent layout
            targetOffset = it
                .positionInParent()
                .round()
        }
        .offset {
            // Animate to the new target offset when alignment changes.
            val anim = animatable ?: Animatable(targetOffset, IntOffset.VectorConverter)
                .also {
                    animatable = it
                }


            if (anim.targetValue != targetOffset) {
                scope.launch {
                    anim.animateTo(targetOffset, spring(stiffness = Spring.StiffnessMediumLow))
                }
            }
            // Offset the child in the opposite direction to the targetOffset, and slowly catch
            // up to zero offset via an animation to achieve an overall animated movement.
            animatable?.let { it.value - targetOffset } ?: IntOffset.Zero
        }
}

这是一个用于修改Composable的Modifier,可以使用在以下的Composable中:

@Composable
fun AnimatedChildArrangement(arrangement: Arrangement.Vertical) {
    Column(
        Modifier
            .fillMaxSize()
            .padding(4.dp)
            .border(2.dp, Color.Green),
        verticalArrangement = arrangement
    ) {
        Box(
            modifier = Modifier
                .animatePlacement()
                .size(100.dp)
                .background(Color.Red)
        )
    }
}

你可以在Demo中使用这个Composable来测试效果:

@Preview
@Composable
private fun Test() {

    var arrangement: Arrangement.Vertical by remember {
        mutableStateOf(Arrangement.Center)
    }

    Column {
        Button(onClick = {
            arrangement = if (arrangement == Arrangement.Center) {
                Arrangement.Top
            } else {
                Arrangement.Center

            }
        }) {
            Text(text = "arrangement: $arrangement")
        }

        AnimatedChildArrangement(arrangement = arrangement)
    }
}

以上是你要翻译的部分。

英文:

It can be done with Modifier.onPlaced and Modifier.offset by creating a Modifier

fun Modifier.animatePlacement(): Modifier = composed {
    val scope = rememberCoroutineScope()
    var targetOffset by remember { mutableStateOf(IntOffset.Zero) }
    var animatable by remember {
        mutableStateOf&lt;Animatable&lt;IntOffset, AnimationVector2D&gt;?&gt;(null)
    }
    this
        // &#128293; onPlaced should be before offset Modifier
        .onPlaced {
            // Calculate the position in the parent layout
            targetOffset = it
                .positionInParent()
                .round()
        }
        .offset {
            // Animate to the new target offset when alignment changes.
            val anim = animatable ?: Animatable(targetOffset, IntOffset.VectorConverter)
                .also {
                    animatable = it
                }


            if (anim.targetValue != targetOffset) {
                scope.launch {
                    anim.animateTo(targetOffset, spring(stiffness = Spring.StiffnessMediumLow))
                }
            }
            // Offset the child in the opposite direction to the targetOffset, and slowly catch
            // up to zero offset via an animation to achieve an overall animated movement.
            animatable?.let { it.value - targetOffset } ?: IntOffset.Zero
        }
}

Some Composable that this modifier is assigned to

@Composable
fun AnimatedChildArrangement(arrangement: Arrangement.Vertical) {
    Column(
        Modifier
            .fillMaxSize()
            .padding(4.dp)
            .border(2.dp, Color.Green),
        verticalArrangement = arrangement
    ) {
        Box(
            modifier = Modifier
                .animatePlacement()
                .size(100.dp)
                .background(Color.Red)
        )
    }
}

Demo

@Preview
@Composable
private fun Test() {

    var arrangement: Arrangement.Vertical by remember {
        mutableStateOf(Arrangement.Center)
    }

    Column {
        Button(onClick = {
            arrangement = if (arrangement == Arrangement.Center) {
                Arrangement.Top
            } else {
                Arrangement.Center

            }
        }) {
            Text(text = &quot;arrangement: $arrangement&quot;)
        }

        AnimatedChildArrangement(arrangement = arrangement)
    }
}

huangapple
  • 本文由 发表于 2023年6月5日 19:55:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76406176.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定