Jetpack Compose 中的 MotionLayout

MotionLayout in Jetpack Compose

This might be a little soon, but there should be a workaround for this

TL;DR

有没有办法在 MotionLayout 中使用 Jetpack Compose 的 Composable 组件?
MotionLayout 或 Compose 的路线图中有这样的组合吗?


在 Jetpack compose 中是否有替代品可以实现同样的功能?

由于任何view想在motion scene中修改,compose函数在motion scene中是不能修改的。

问题

我想在 Surface 的中心设置一个图像的动画,并在特定的持续时间内放大和缩小它。

使用动画,您可以在每个步骤中定义关键帧。

Ui 是使用 Composable 函数 制作的。 如何使用 Compose 中的 MotionLayout 完成我能做的事情?


Jetpack 组合:v1.0.0-alpha02

你应该使用transitionDefinition,检查下面的例子并根据你的需要采用它。

enum class State {
    A, B
}

private val scale = FloatPropKey()
private val definition = transitionDefinition {
    state(State.A) {
        this[scale] = 1f
    }
    state(State.B) {
        this[scale] = 5f
    }
    transition(fromState = State.A, toState = State.B) {
        scale using tween(
            durationMillis = 3000,
            easing = FastOutSlowInEasing
        )
    }
}

@Composable
fun AnimateComponentScale() {
    var initialState by remember { mutableStateOf(State.A) }
    var toState by remember { mutableStateOf(State.B) }

    val state = transition(
        definition = definition,
        initState = initialState,
        toState = toState
    ) { state ->
        when (state) {
            State.A -> {
                initialState = State.A
                toState = State.B
            }
            State.B -> {
                initialState = State.B
                toState = State.A
            }
        }
    }
    Box(
        modifier = Modifier.fillMaxSize(),
        gravity = ContentGravity.Center,
        backgroundColor = Color.Cyan
    ) {
        Canvas(modifier = Modifier.preferredSize(50.dp)) {
            scale(scaleX = state[scale], scaleY = state[scale]) {
                drawRect(color = Color(255, 138, 128))
            }
        }
    }
}

您现在可以使用最新版本的 constraintlayout-compose(撰写本文时 1.0.0-beta02)在 Compose 中使用 MotionLayout 功能方向的子集。

文档中的说明显示您可以将其添加到您的项目中:

dependencies {
    implementation("androidx.constraintlayout:constraintlayout-compose:1.0.0-beta02")
}

文档还提供了一个在两个约束集之间转换的简单示例:

@Preview(group = "motion8")
@Composable
public fun AttributesRotationXY() {
    var animateToEnd by remember { mutableStateOf(false) }

    val progress by animateFloatAsState(
        targetValue = if (animateToEnd) 1f else 0f,
        animationSpec = tween(6000)
    )
    Column {
        MotionLayout(
            modifier = Modifier
                .fillMaxWidth()
                .height(400.dp)
                .background(Color.White),
            motionScene = MotionScene("""{
                ConstraintSets: {   // all ConstraintSets
                  start: {          // constraint set id = "start"
                    a: {            // Constraint for widget id='a'
                      width: 40,
                      height: 40,
                      start: ['parent', 'start', 16],
                      bottom: ['parent', 'bottom', 16]
                    }
                  },
                  end: {         // constraint set id = "start"
                    a: {
                      width: 40,
                      height: 40,
                      //rotationZ: 390,
                      end: ['parent', 'end', 16],
                      top: ['parent', 'top', 16]
                    }
                  }
                },
                Transitions: {            // All Transitions in here 
                  default: {              // transition named 'default'
                    from: 'start',        // go from Transition "start"
                    to: 'end',            // go to Transition "end"
                    pathMotionArc: 'startHorizontal',  // move in arc 
                    KeyFrames: {          // All keyframes go here
                      KeyAttributes: [    // keyAttributes key frames go here
                        {
                          target: ['a'],              // This keyAttributes group target id "a"
                          frames: [25,50,75],         // 3 points on progress 25% , 50% and 75%
                          rotationX: [0, 45, 60],     // the rotationX angles are a spline from 0,0,45,60,0
                          rotationY: [60, 45, 0],     // the rotationX angles are a spline from 0,60,45,0,0
                        }
                      ]
                    }
                  }
                }
            }"""),
            debug = EnumSet.of(MotionLayoutDebugFlags.SHOW_ALL),
            progress = progress) {
            Box(modifier = Modifier
                .layoutId("a")
                .background(Color.Red))
        }

        Button(onClick = { animateToEnd = !animateToEnd }) {
            Text(text = "Run")
        }
    }
}

您可以阅读更多内容并关注 this wiki and the constraint layout repository 中的进展。