具有 3 个视图和屏障的 MotionLayout

MotionLayout with 3 Views and Barrier

我想用 3 张卡片创建一些视图:

如果我点击左卡或右卡,它就会出现在顶卡的位置(卡交换它们的位置)

但是如果我点击右边的卡片,那么动画看起来很奇怪

首先在一些动画之后它看起来符合预期

我为动画创建了运动场景

<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

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

        <Constraint android:id="@id/left_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toStartOf="@id/right_card"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

        <Constraint android:id="@id/right_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toEndOf="@id/left_card"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

        <Constraint
            android:id="@id/barrier"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="left_card,right_card" />

        <Constraint android:id="@id/center_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/barrier" />

            <Transform
                android:scaleX="1"
                android:scaleY="1" />

        </Constraint>

    </ConstraintSet>

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

        <Constraint android:id="@id/left_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toEndOf="@id/center_card"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

        <Constraint android:id="@id/right_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/barrier" />

            <Transform
                android:scaleX="1"
                android:scaleY="1" />

        </Constraint>

        <Constraint
            android:id="@id/barrier"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="left_card,center_card" />

        <Constraint android:id="@id/center_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toStartOf="@id/left_card"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

    </ConstraintSet>

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

        <Constraint android:id="@id/left_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/barrier" />

            <Transform
                android:scaleX="1"
                android:scaleY="1" />

        </Constraint>

        <Constraint android:id="@id/right_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toStartOf="@id/center_card"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

        <Constraint
            android:id="@id/barrier"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="right_card,center_card" />

        <Constraint android:id="@id/center_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toEndOf="@id/right_card"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

    </ConstraintSet>

    <ConstraintSet
        android:id="@+id/swipeFromLeftToBottom"
        app:deriveConstraintsFrom="@id/center_on_left">

        <Constraint android:id="@id/left_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toStartOf="@id/right_card"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

        <Constraint android:id="@id/right_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toEndOf="@id/left_card"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

        <Constraint
            android:id="@id/barrier"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="left_card,right_card" />

        <Constraint android:id="@id/center_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/barrier" />

            <Transform
                android:scaleX="1"
                android:scaleY="1" />

        </Constraint>

    </ConstraintSet>

    <ConstraintSet
        android:id="@+id/swipeFromRightToBottom"
        app:deriveConstraintsFrom="@id/center_on_right">

        <Constraint android:id="@id/left_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toStartOf="@id/right_card"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

        <Constraint android:id="@id/right_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toEndOf="@id/left_card"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

        <Constraint
            android:id="@id/barrier"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="left_card,right_card" />

        <Constraint android:id="@id/center_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/barrier" />

            <Transform
                android:scaleX="1"
                android:scaleY="1" />

        </Constraint>

    </ConstraintSet>

    <ConstraintSet
        android:id="@+id/swipeFromBottomToLeft"
        app:deriveConstraintsFrom="@id/center_on_bottom">

        <Constraint android:id="@id/left_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toEndOf="@id/center_card"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

        <Constraint android:id="@id/right_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/barrier" />

            <Transform
                android:scaleX="1"
                android:scaleY="1" />

        </Constraint>

        <Constraint
            android:id="@id/barrier"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="left_card,center_card" />

        <Constraint android:id="@id/center_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toStartOf="@id/left_card"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

    </ConstraintSet>

    <ConstraintSet
        android:id="@+id/swipeFromRightToLeft"
        app:deriveConstraintsFrom="@id/center_on_right">

        <Constraint android:id="@id/left_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toEndOf="@id/center_card"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

        <Constraint android:id="@id/right_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/barrier" />

            <Transform
                android:scaleX="1"
                android:scaleY="1" />

        </Constraint>

        <Constraint
            android:id="@id/barrier"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="left_card,center_card" />

        <Constraint android:id="@id/center_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toStartOf="@id/left_card"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

    </ConstraintSet>

    <ConstraintSet
        android:id="@+id/swipeFromBottomToRight"
        app:deriveConstraintsFrom="@id/center_on_bottom">

        <Constraint android:id="@id/left_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/barrier" />

            <Transform
                android:scaleX="1"
                android:scaleY="1" />

        </Constraint>

        <Constraint android:id="@id/right_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toStartOf="@id/center_card"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

        <Constraint
            android:id="@id/barrier"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="right_card,center_card" />

        <Constraint android:id="@id/center_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toEndOf="@id/right_card"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

    </ConstraintSet>

    <ConstraintSet
        android:id="@+id/swipeFromLeftToRight"
        app:deriveConstraintsFrom="@id/center_on_left">

        <Constraint android:id="@id/left_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/barrier" />

            <Transform
                android:scaleX="1"
                android:scaleY="1" />

        </Constraint>

        <Constraint android:id="@id/right_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toStartOf="@id/center_card"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

        <Constraint
            android:id="@id/barrier"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="right_card,center_card" />

        <Constraint android:id="@id/center_card">

            <Layout
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_margin="@dimen/layout_margin"
                app:layout_constraintBottom_toTopOf="@id/barrier"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHeight_percent="0.2"
                app:layout_constraintStart_toEndOf="@id/right_card"
                app:layout_constraintTop_toTopOf="parent" />

            <Transform
                android:scaleX="0.90"
                android:scaleY="0.90" />

        </Constraint>

    </ConstraintSet>

</MotionScene>

和运动布局

<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/motion_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/scene_swipe"
    app:motionDebug="SHOW_ALL">

    <FrameLayout
        android:id="@+id/left_card"
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:background="@drawable/cave"
        android:backgroundTint="@color/primaryDarkGreen"
        app:layout_constraintBottom_toTopOf="@id/barrier"
        android:scaleX="0.90"
        android:scaleY="0.90">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_marginEnd="40dp"
            android:layout_marginBottom="40dp"
            android:text="Left card" />

    </FrameLayout>

    <FrameLayout
        android:id="@+id/right_card"
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:background="@drawable/cave"
        android:backgroundTint="@color/primaryDarkSlateBlue"
        app:layout_constraintBottom_toTopOf="@id/barrier"
        android:scaleX="0.90"
        android:scaleY="0.90">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_marginEnd="40dp"
            android:layout_marginBottom="40dp"
            android:text="Right card" />

    </FrameLayout>

    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="bottom"
        app:constraint_referenced_ids="left_card,right_card" />

    <FrameLayout
        android:id="@+id/center_card"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@drawable/cave"
        android:backgroundTint="@color/primaryPink"
        app:layout_constraintTop_toBottomOf="@id/barrier">

        <TextView
            android:id="@+id/likeButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_marginEnd="40dp"
            android:layout_marginBottom="40dp"
            android:text="Top card" />

    </FrameLayout>

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

在我的片段中,我根据上一个动画设置了动画

private int curState = R.id.swipeFromLeftToBottom;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.swipe_card, container, false);
    ...

    leftCard.setOnClickListener(view -> swipe(1));
    rightCard.setOnClickListener(view -> swipe(2));
    centerCard.setOnClickListener(view -> swipe(3));

    motionLayout.transitionToState(R.id.swipeFromLeftToBottom);

    motionLayout.setTransitionListener(new TransitionAdapter() {
        @Override
        public void onTransitionCompleted(MotionLayout motionLayout, int swipeId) {
            curState = swipeId;
        }
    });

    return rootView;
}

private void swipe(int card) {
    // swipeFromLeftToBottom    Left Right Bottom
    // swipeFromRightToBottom   Left Right Bottom
    // swipeFromBottomToLeft    Bottom Left Right
    // swipeFromRightToLeft     Bottom Left Right
    // swipeFromBottomToRight   Right Bottom Left
    // swipeFromLeftToRight     Right Bottom Left

    // ignore swipe if big layout clicked
    if ((curState == R.id.swipeFromLeftToBottom || curState == R.id.swipeFromRightToBottom) && card == 3 ||
            (curState == R.id.swipeFromBottomToLeft || curState == R.id.swipeFromRightToLeft) && card == 2 ||
            (curState == R.id.swipeFromBottomToRight || curState == R.id.swipeFromLeftToRight) && card == 1) {
        return;
    }

    int motion =
            curState == R.id.swipeFromLeftToBottom || curState == R.id.swipeFromRightToBottom ?
                    card == 1 ? R.id.swipeFromBottomToRight : R.id.swipeFromBottomToLeft :

                    curState == R.id.swipeFromBottomToLeft || curState == R.id.swipeFromRightToLeft ?
                            card == 3 ? R.id.swipeFromLeftToBottom : R.id.swipeFromLeftToRight :

                            card == 2 ? R.id.swipeFromRightToLeft : R.id.swipeFromRightToBottom;

    motionLayout.transitionToState(motion);
}

我哪里搞错了?

是不是因为Barrier,第一个动画没有渲染出来?

我该如何解决?

拜托,帮忙。

一组

app:layout_constraintHeight_percent="0.8"

所有在大布局的地方通过过渡的视图都解决了这个问题