最近有点闲,看了看新东西,无意间发现了Motionlayout这个东西,挺有趣的,真正项目能不能用上先两说,就当扩展知识库了
ConstraintLayout 是他的直接父类,也就是说约束布局的所有属性他也都能用
public class MotionLayout extends ConstraintLayout
先说怎么引用
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-rc1'
再看效果实现
这个东西可以实现很多酷炫的动画效果,我这个旋转只是冰山一角,有空再深入了解吧
在布局文件中写下这个控件然后一定记得给他的子view赋上id,后边要用
<?xml version="1.0" encoding="utf-8"?>
<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_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:motionDebug="SHOW_PATH"
app:layoutDescription="@xml/activity_motionlayout_scene">
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<SeekBar
android:id="@+id/progress"
android:layout_width="100dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.motion.widget.MotionLayout>
这里边最关键的地方就是app:layoutDescription这个属性,需要配置MotionScene xml文件。这就类似于我们平常自定义的drawable文件。app:motionDebug="SHOW_PATH" 调试属性是可以预览动画的运动轨迹。
接下来是motionscen里边的写法,动画控制都在这个xml里实现,基本的动画效果都可以实现,并且跟你的手势或者点击联动,其中设置关键帧是调整动画效果的重中之中,我接下来放的三个例子都是基于手势滑动完成的动画,先看个普通的直线运动
<?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">
<ConstraintSet android:id="@+id/btn_start">
<Constraint
android:id="@+id/btn"
android:layout_width="100dp"
android:layout_height="60dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/btn_end">
<Constraint
android:id="@+id/btn"
android:layout_width="100dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</ConstraintSet>
<Transition
android:id="@+id/btn_transition"
app:constraintSetEnd="@id/btn_end"
app:constraintSetStart="@+id/btn_start"
app:duration="2000">
<OnSwipe app:touchAnchorId="@id/btn" />
</Transition>
</MotionScene>
<ConstraintSet android:id="@+id/btn_end">
<Constraint
android:id="@+id/btn"
android:layout_width="100dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</ConstraintSet>
如果把结束位置的宽高变一下,那么这个动画就会变成这样
这个是不加关键帧的一个普通直上直下的动画写法,这个MotionScene其实Androidstudio里边可以自动生成,你只需要自己去写上对应id和动画效果就行了,或者自己去xml文件夹创建,效果是一样的,最终都是要写到布局文件的app:layoutDescription这个属性中,MotionScene.xml可以理解为是布局文件中Motionlayout这个布局中的子view的解释文件,解释他如何去运动,类似style
这个里边ConstraintSet 是用来表示motionlayout里边的子view的约束和位置的,之前在布局文件里我不是没有定位置么,可以在这里边做,然后id要对应上子viewid,写了两个给上动画开始和动画结束的位置,中间的过程系统会自动帮你实现,不做任何操作的时候就默认走直线了。
Transition是用来控制动画的,可以叫他控制器,这里边填写上开始和结束的constraintset的id,然后可以表明运动时间app:duration="2000",还可以表明通过什么操作开始运动 <OnSwipe>表示根据手势滑动,而之前说的关键帧<KeyFrameSet>也是写在控制器里的,开始的曲线运动就是通过这个实现
这是控制器里的xml写法
<Transition
android:id="@+id/btn_transition"
app:constraintSetEnd="@id/btn_end"
app:constraintSetStart="@+id/btn_start"
app:duration="2000">
<KeyFrameSet>
<KeyPosition
app:framePosition="50"
app:motionTarget="@id/btn"
app:pathMotionArc="flip"
app:percentY="0.5" />
<KeyPosition
app:framePosition="25"
app:motionTarget="@id/btn"
app:pathMotionArc="flip"
app:percentX="0.25" />
<KeyPosition
app:framePosition="75"
app:motionTarget="@id/btn"
app:pathMotionArc="flip"
app:percentX="1" />
<KeyPosition
app:framePosition="25"
app:keyPositionType="parentRelative"
app:motionTarget="@id/btn"
app:percentX="0.7"
app:percentY="0.6" />
<KeyPosition
app:framePosition="50"
app:keyPositionType="parentRelative"
app:motionTarget="@id/btn"
app:percentX="0.85" />
<KeyPosition
app:framePosition="75"
app:keyPositionType="parentRelative"
app:motionTarget="@id/btn"
app:percentX="0.7"
app:percentY="0.4" />
<!-- apply other animation attributes-->
<!-- 前半段的动画效果:逆时针旋转一圈-->
<KeyAttribute
android:rotation="-360"
app:framePosition="50"
app:motionTarget="@id/btn" />
<!--后半段的动画效果:逆时针旋转一圈-->
<KeyAttribute
android:rotation="-720"
app:framePosition="100"
app:motionTarget="@id/btn" />
</KeyFrameSet>
<OnSwipe app:touchAnchorId="@id/btn" />
</Transition>
其中KeyPosition就是具体到某个点的时候view所处的位置 通过这两个属性控制 app:percentX="0.7" app:percentY="0.6" 范围0-1代表所处xy轴百分比位置,而 app:framePosition="25"就是代表了当前动画运动到什么进度了,1-100 的范围 50代表运动到一半了连起来就是,动画进行到25%的时候view的坐标在x轴的70%y轴的60%的位置上,然后我们的曲线路径就是通过加多个关键帧实现的效果
KeyAttribute这个是代表属性变化,比如现在的转转效果android:rotation就是加在这里边,同样的可以加android:alpha做渐变透明或者其他效果,我就不展示了。
app:keyPositionType="parentRelative"这个属性是用来表示你是基于那个坐标系来运动的,比如parentRelative就是基于你的父布局一般用这个就够了,其他两个我还没研究明白
就这样吧
写布局就用约束布局加线性布局加相对布局组合着用吧
layout_constraintLeft_toLeftOf 我的左边在...的左边
layout_constraintLeft_toRightOf 我的左边在...的右边
layout_constraintRight_toLeftOf 我的右边在...的左边
layout_constraintRight_toRightOf 我的右边在...的右边
layout_constraintTop_toTopOf 我的上边在...的上边
layout_constraintTop_toBottomOf 我的上边在...的下边
layout_constraintBottom_toTopOf 我的下边在...的上边
layout_constraintBottom_toBottomOf 我的下边在...的下边
layout_constraintBaseline_toBaselineOf 多用于文字底线对齐
居中就是top-top bottom-bottom left-left right-right全部填父布局
这个控件写完 每个view的属性一大摞 但是页面整体层级很浅,对性能也算是一定的提升,再有就是可以预览界面拖拽布局,方便的很
尤其是你在写一些item的布局时,里边标签一大堆,用相对布局跟线性布局真的写着很累心,层级一多看着也很累心,希望用约束布局的越来越多