如何使用 Motion Layout 设置 ImageView 的位置
How to set a position of ImageView using Motion Layout
我知道如何将对象(例如图像视图)从起点移动到终点,
((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>
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
class,只留下一个过渡(从开始到end) 并在其中实现自己的逻辑。
关键是覆盖 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% 之间的某个地方停止,用户将能够继续在两个方向上滑动。
我知道如何将对象(例如图像视图)从起点移动到终点,
((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>
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
class,只留下一个过渡(从开始到end) 并在其中实现自己的逻辑。
关键是覆盖 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% 之间的某个地方停止,用户将能够继续在两个方向上滑动。