如何在单个视图上创建多个转换

How to create multiple transitions on a single view

是否可以实现draggable panel! 使用运动布局?

我尝试通过在单个视图上使用多个 Transitions 和 OnSwipe 来玩转 google 类似 youtube 的示例,但未能成功。谁能指导我实现如何在同一视图上使用 OnSwipe 应用两个转换?

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <Transition
        app:constraintSetEnd="@id/expanded"
        app:constraintSetStart="@id/collapsed"
        app:duration="100"
        app:interpolator="easeInOut">

        <OnSwipe
            app:dragDirection="dragUp"
            app:maxAcceleration="200"
            app:touchAnchorId="@+id/videoViewContainer"
            app:touchAnchorSide="top" />


        <KeyFrameSet>
            <!--<KeyAttribute-->
                <!--app:framePosition="0"-->
                <!--app:target="@id/videoView">-->
                <!--<CustomAttribute-->
                    <!--app:attributeName="EndPadding"-->
                    <!--app:customDimension="@dimen/video_view_right_padding" />-->
            <!--</KeyAttribute>-->

            <!--<KeyAttribute-->
                <!--app:framePosition="20"-->
                <!--app:target="@id/videoView">-->
                <!--<CustomAttribute-->
                    <!--app:attributeName="EndPadding"-->
                    <!--app:customDimension="0dp" />-->
            <!--</KeyAttribute>-->

            <KeyAttribute
                app:framePosition="0"
                app:target="@id/videoMotionLayout">
                <CustomAttribute
                    app:attributeName="height"
                    app:customDimension="90dp" />
            </KeyAttribute>

            <KeyAttribute
                app:framePosition="20"
                app:target="@id/videoMotionLayout">
                <CustomAttribute
                    app:attributeName="height"
                    app:customDimension="250dp" />
            </KeyAttribute>

            <KeyAttribute
                app:framePosition="0"
                app:target="@id/videoMotionLayout">
                <CustomAttribute
                    app:attributeName="width"
                    app:customDimension="160dp" />
            </KeyAttribute>

            <KeyAttribute
                app:framePosition="20"
                app:target="@id/videoMotionLayout">
                <CustomAttribute
                    app:attributeName="width"
                    app:customDimension="0dp" />
            </KeyAttribute>

            <KeyAttribute
                android:alpha="0"
                app:framePosition="0"
                app:target="@id/videoRecyclerView" />

            <KeyAttribute
                android:alpha="1"
                app:framePosition="100"
                app:target="@id/videoRecyclerView" />

            <KeyAttribute
                app:framePosition="0"
                app:target="@id/videoViewContainer">
                <CustomAttribute
                    app:attributeName="cardElevation"
                    app:customDimension="5dp" />
            </KeyAttribute>

            <KeyAttribute
                app:framePosition="3"
                app:target="@id/videoViewContainer">
                <CustomAttribute
                    app:attributeName="cardElevation"
                    app:customDimension="0dp" />
            </KeyAttribute>

        </KeyFrameSet>
    </Transition>


    <Transition
        app:constraintSetEnd="@id/close"
        app:constraintSetStart="@id/close"
        app:duration="100"
        app:interpolator="easeInOut">

        <OnSwipe
            app:dragDirection="dragLeft"
            app:maxAcceleration="200"
            app:touchAnchorId="@+id/videoViewContainer"
            app:touchAnchorSide="top" />


        <KeyFrameSet>
            <KeyAttribute
                app:framePosition="0"
                app:target="@id/videoMotionLayout">
            </KeyAttribute>
        </KeyFrameSet>
    </Transition>

    <Transition
        app:constraintSetEnd="@id/close"
        app:constraintSetStart="@id/close"
        app:duration="100"
        app:interpolator="easeInOut">

        <OnSwipe
            app:dragDirection="dragRight"
            app:maxAcceleration="200"
            app:touchAnchorId="@+id/videoViewContainer"
            app:touchAnchorSide="top" />


        <KeyFrameSet>

        </KeyFrameSet>
    </Transition>

    <ConstraintSet android:id="@+id/close">

        <Constraint
            android:id="@id/videoViewContainer"
            android:layout_height="250dp"
            android:layout_marginStart="0dp"
            android:layout_marginEnd="0dp"
            android:layout_marginBottom="0dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Constraint
            android:id="@id/content"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginStart="0dp"
            android:layout_marginEnd="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/videoViewContainer" />

    </ConstraintSet>

    <ConstraintSet android:id="@+id/collapsed">

        <Constraint
            android:id="@id/videoViewContainer"
            android:layout_height="113dp"
            android:layout_width="200dp"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginBottom="65dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"/>

        <Constraint
            android:id="@id/content"
            android:layout_width="match_parent"
            android:layout_height="-1dp"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginBottom="66dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/videoViewContainer" />

    </ConstraintSet>

</MotionScene>


如果我也可以将迷你播放器场景移动到左右方向,那将很有帮助。谢谢。

How to create multiple transitions on a single view

可以向同一个视图添加多个转换。例如,我们可以在相同的 touchAnchorId 上定义 motion:dragDirection="dragDown"motion:dragDirection="dragUp" 的动画,没有任何问题。可能的配置如下,

  motion:dragDirection="dragUp"
  motion:dragDirection="dragDown"
  motion:dragDirection="dragLeft"
  motion:dragDirection="dragRight"

做什么

所以,在这里我将向您展示如何在同一个视图上一起实现所有这些。 在编写任何代码之前,请查看下面的 gif 以更好地理解我们正在尝试创建的内容。

怎么做

添加ConstraintLayout依赖:

dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2'
 }

创建 MotionLayout 文件:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/motionLayout"
    motion:layoutDescription="@xml/motionscene1"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="240dp"
        android:background="#453672"
        motion:layout_constraintStart_toStartOf="parent"
        motion:layout_constraintTop_toTopOf="parent"/>

</androidx.constraintlayout.motion.widget.MotionLayout>

创建一个 MotionScene: MotionScene 是一个 XML 资源文件,其中包含相应布局的所有运动描述。将文件放在res/xml/文件夹下

motionscene1.xml

 <?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto">

    <!-- top to bottom right-->
    <Transition
        motion:constraintSetEnd="@id/step2"
        motion:constraintSetStart="@id/step1"

        motion:duration="500">
        <OnSwipe
            motion:dragDirection="dragDown"
            motion:touchAnchorId="@id/image"
            motion:touchAnchorSide="top" />
    </Transition>
    <!-- bottom right to bottom left-->
    <Transition
        motion:constraintSetEnd="@id/step3"
        motion:constraintSetStart="@id/step2"

        motion:duration="500">
        <OnSwipe
            motion:dragDirection="dragLeft"
            motion:touchAnchorId="@id/image"
            motion:touchAnchorSide="left" />
    </Transition>

    <!-- bottom left to top-->
    <Transition
        motion:constraintSetEnd="@id/step1"
        motion:constraintSetStart="@id/step3"

        motion:duration="500">
        <OnSwipe
            motion:dragDirection="dragUp"
            motion:touchAnchorId="@id/image"
            motion:touchAnchorSide="top" />
    </Transition>
    <!-- bottom right to top-->
    <Transition
        motion:constraintSetEnd="@id/step1"
        motion:constraintSetStart="@id/step2"

        motion:duration="500">
        <OnSwipe
            motion:dragDirection="dragUp"
            motion:touchAnchorId="@id/image"
            motion:touchAnchorSide="top" />
    </Transition>
    <!-- place the view on top-->
    <ConstraintSet android:id="@+id/step1">
        <Constraint
            android:id="@id/image"
            android:layout_width="match_parent"
            android:layout_height="240dp"
            android:layout_marginStart="0dp"
            android:layout_marginLeft="0dp"
            android:layout_marginTop="0dp"
            android:layout_marginEnd="0dp"
            android:layout_marginRight="0dp"
            android:layout_marginBottom="0dp"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent">
            <PropertySet android:alpha="1" />
        </Constraint>
    </ConstraintSet>
    <!-- place the view on bottom right-->
    <ConstraintSet android:id="@+id/step2">
        <Constraint
            android:id="@id/image"
            android:layout_width="150dp"
            android:layout_height="100dp"
            android:layout_marginStart="16dp"
            android:layout_marginLeft="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="16dp"
            android:layout_marginRight="16dp"
            android:layout_marginBottom="16dp"

            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintEnd_toEndOf="parent">
            <PropertySet android:alpha="1" />
        </Constraint>
    </ConstraintSet>
    <!-- place the view on bottom left-->
    <ConstraintSet android:id="@+id/step3">
        <Constraint
            android:id="@id/image"
            android:layout_width="150dp"
            android:layout_height="100dp"
            android:layout_marginStart="16dp"
            android:layout_marginLeft="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="16dp"
            android:layout_marginRight="16dp"
            android:layout_marginBottom="16dp"

            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintStart_toStartOf="parent">
            <PropertySet android:alpha="1" />
        </Constraint>
    </ConstraintSet>


</MotionScene>

就是这样。您无需编写任何 java/kotlin 代码就创建了一个惊人的自定义动画。 MotionLayout 是完全声明式的,这意味着您可以在 XML 中描述任何转换,无论多么复杂。