Android MotionLayout ImageView点击旋转反向及状态重置问题咨询
MotionLayout点击旋转二次点击反向问题解决方案
问题描述
- 基于MotionLayout实现ImageView旋转交互,首次点击目标ImageView可按预期顺时针完成旋转,符合开发预期
- 第二次点击控件时图片变为逆时针旋转,尝试多种重置图片旋转状态的方案均未生效
原有MotionScene配置代码
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetEnd="@+id/end" motion:constraintSetStart="@id/start" motion:duration="1500"> <OnClick motion:clickAction="toggle" motion:targetId="@id/img_reload_cast_dialog"/> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/img_reload_cast_dialog" motion:layout_constraintEnd_toStartOf="@id/img_help_cast_dialog" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/_20sdp" motion:layout_constraintTop_toTopOf="parent" > <Transform android:rotation="0" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/img_reload_cast_dialog" motion:layout_constraintEnd_toStartOf="@id/img_help_cast_dialog" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/_20sdp" motion:layout_constraintTop_toTopOf="parent" > <Transform android:rotation="720" /> </Constraint> </ConstraintSet> </MotionScene>
问题根因
问题出在OnClick配置的motion:clickAction="toggle"属性:
- toggle动作的默认逻辑是在start、end两个约束集之间双向切换状态
- 首次点击时状态从start(旋转0度)切到end(旋转720度),表现为顺时针旋转2圈
- 第二次点击时状态会从end反向切回start,也就是从720度旋转回0度,自然表现为逆时针旋转,和状态重置逻辑无关
修复方案
步骤1:修改点击动作类型
将原有OnClick标签的clickAction属性从toggle改为transitionToEnd,让点击只触发从start到end的正向旋转动画:
<OnClick motion:clickAction="transitionToEnd" motion:targetId="@id/img_reload_cast_dialog"/>
步骤2:添加动画完成监听,无动画重置初始状态
给MotionLayout设置过渡监听,每次动画执行到end状态完成旋转后,瞬间无动画切回start约束集,用户无感知,下次点击可再次触发顺时针旋转:
motionLayout.setTransitionListener(object : MotionLayout.TransitionListener { override fun onTransitionStarted(motionLayout: MotionLayout?, startId: Int, endId: Int) { // 动画开始时禁用点击,避免重复触发冲突 findViewById<View>(R.id.img_reload_cast_dialog).isClickable = false } override fun onTransitionChange(motionLayout: MotionLayout?, startId: Int, endId: Int, progress: Float) {} override fun onTransitionTrigger(motionLayout: MotionLayout?, triggerId: Int, positive: Boolean, progress: Float) {} override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) { if (currentId == R.id.end) { // 无动画瞬间重置回初始状态 motionLayout?.setState(R.id.start, 0, 0) } // 重置完成恢复点击 findViewById<View>(R.id.img_reload_cast_dialog).isClickable = true } })
注意:如果使用Java开发,逻辑完全一致,替换为对应Java写法即可,不需要修改MotionScene里的约束属性。
内容的提问来源于stack exchange,提问作者ninhnau19
相关产品推荐
相关产品推荐

