【问题标题】:How to set a position of ImageView using Motion Layout如何使用 Motion Layout 设置 ImageView 的位置
【发布时间】:2020-07-05 09:32:54
【问题描述】:

我知道如何移动对象(例如图像视图)从起点结束,

((MotionLayout)findViewById(R.id.motionLayout)).transitionToEnd();

但是当我点击一个按钮时,如何将对象移动到keyPosition

如果不可能,我必须使用哪些工具来做到这一点?

example screenshot

运动布局代码:

motion_06_keyframe.xml

<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/motionLayout"
    app:layoutDescription="@xml/scene_06"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/button"
        android:background="@color/colorAccent"
        android:layout_width="64dp"
        android:layout_height="64dp" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="36dp"
        android:text="Button"
        android:onClick="lol"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.47"
        app:layout_constraintStart_toStartOf="parent" />

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

scene_06.xml

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

    <Transition
        motion:constraintSetStart="@+id/start"
        motion:constraintSetEnd="@+id/end"
        motion:duration="1000"
        motion:motionInterpolator="linear">
        <OnSwipe
            motion:touchAnchorId="@+id/button"
            motion:touchAnchorSide="right"
            motion:dragDirection="dragRight" />

        <KeyFrameSet>
            <KeyPosition
                motion:keyPositionType="pathRelative"
                motion:percentY="-0.25"
                motion:framePosition="50"
                motion:motionTarget="@id/button"/>
        </KeyFrameSet>
    </Transition>

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@id/button"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginStart="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="BackgroundColor"
                motion:customColorValue="#D81B60"/>
        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@id/button"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginEnd="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="BackgroundColor"
                motion:customColorValue="#9999FF"/>
        </Constraint>
    </ConstraintSet>

</MotionScene>

【问题讨论】:

    标签: android android-animation android-motionlayout


    【解决方案1】:

    KeyPosition 定义动画应该经过的状态,你不能使用默认工具停止过渡。 最好的选择是将您的过渡分为两部分:

    1) 从中间开始
    2) 中到尾

    但问题是,如果当前状态处于中间状态,MotionLayout 将不知道您想转换到哪里。它需要 xml 文件中的第一个转换,因此您必须手动更改它以执行第二个转换。

    View button; // the button
    boolean weWantTransitionToEnd; // depends on your logic, you can throw it away
    MotionLayout motionLayout; // the layout
    button.setOnClickListener(view -> {
                    switch (motionLayout.getCurrentState()) {
                        case R.id.start:
                            motionLayout.transitionToEnd();
                            break;
                        case R.id.middle:
                            if (weWantTransitionToEnd) {
                                motionLayout.setTransition(R.id.middle, R.id.end);
                                motionLayout.transitionToEnd();
                            } else {
                                motionLayout.setTransition(R.id.start, R.id.middle);
                                motionLayout.transitionToStart();
                            }
                            break;
                        case R.id.end:
                            motionLayout.transitionToStart();
                            break;
                    }
                });
    

    但用户将无法正确刷卡。 如果您希望用户能够在两个方向上滑动它并且这个方块在某些情况下粘在中间,您将不得不扩展 MotionLayout 类,只留下一个过渡(从开始到结束)并实现自己的里面的逻辑。

    关键是覆盖OnTouchEvent(MotionEvent event)dispatchTouchEvent(MotionEvent event) 方法。

        private boolean isThumbDown;
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    isThumbDown = true;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    isThumbDown = false;
                    break;
            }
            return super.dispatchTouchEvent(ev);
        }
    
        @SuppressLint("ClickableViewAccessibility")
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (getProgress() > 0.47f && getProgress() < 0.53f && !isThumbDown) return false;
            return super.onTouchEvent(event);
        }
    

    这样,过渡可以在中间的 47% 到 53% 之间停止,并且用户可以继续在两个方向上滑动。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多