MotionLayout
做为ConstraintLayout
子类,在ConstraintLayout 2.0
库被引入,主要用来管理运动和组件的动画。ConstrantLayout
约束布局,用过的人都说好,反正我用着挺爽的。有部分同窗说性能问题,其实对于初中级开发者来讲,暂无需考虑这个,相比本身动手嵌套几层布局强吧,并且更重要的是业务UI的实现,尤为工做量大的时候。android
本文属于入门级别,重点在于扫盲和入门。若是对你有用,欢迎点赞。我的能力有限,有些东西可能理解不透或不对,欢迎指正,很是感谢。bash
配置app
须要将ConstraintLayout
的版本升级到2.0+。布局
AndroidX:
post
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta8'
复制代码
支持库:性能
implementation 'com.android.support.constraint:constraint-layout:2.0.0-beta8'
复制代码
学习MotionLayout
动画可能须要点Transition
和ConstraintLayout
知识点,不了解能够看看文末连接哦。MotionLayout
运动动画定义了在两个状态集(StateSet)或者两个约束集(ConsraintSet
)之间如何进行过渡。状态集与约束集只是过渡动画不一样的组织方式。学习
一、经过Android Studio建立名为activity_motion
的MotionLayout
布局文件。 动画
MotionLayout
布局后会报红,提示建立
MotionScene.xml
文件。
res/xml
文件夹下生成
activity_motion_scene.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/start">
<Constraint android:id="@+id/widget" />
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint android:id="@id/widget" />
</ConstraintSet>
<Transition
app:constraintSetEnd="@id/end"
app:constraintSetStart="@+id/start" />
</MotionScene>
复制代码
此时在activity_motion.xml
布局文件中的MotionLayout
标签会多一个layoutDescription="@xml/activity_motion_scene"
属性,但Android Studio仍是缺乏layoutDescription
属性的错误,须要手动添加上命名空间。spa
<?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:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/activity_motion_scene">
</androidx.constraintlayout.motion.widget.MotionLayout>
复制代码
欧力给,已经学会建立MotionLayout
,但好像没什么卵用。咱们来看看刚刚自动生成的activity_motion_scene.xml
文件。3d
【划重点】根标签MotionScene
有一个defaultDuration
属性,表示全部未指定时间的动画的默认时间,默认为300毫秒。MotionScene
根标签 必须包含Transition
标签,能够有多个Transition
标签。Transition
标签是用来指定动画的开始和结束状态、任何中间状态以及触发动画的动做,能够理解为一个Transition
标签对应一个动画。同时,MotionScene
标签能够包含TransitionSet
标签,这是可选的。TransitionSet
标签主要为Transition
标签提供起始和结束状态的位置和属性。而TransitionSet
标签必须包含一个或多个Constraint
子标签。Constraint
标签用来定义布局中某个View
在动画中某个状态下位置(经过ConstraintLayout
的相关属性来约束)。
充分理解上段话的内容,下面经过实战加深理解:
一、在activity_motion.xml
布局文件增长一个id
为vStartStatus
的正方形View
。并在根标签MotionLayout
添加showPaths="true"
属性,用来显示正方形运动的路径。
<?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:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/activity_motion_scene"
app:showPaths="true">
<View
android:id="@+id/vStartStatus"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@color/colorPrimary" />
</androidx.constraintlayout.motion.widget.MotionLayout>
复制代码
2.将activity_motion_scene.xml
文件中Constraint
标签的id
值修改为正方形的id
,即vStartStatus
。Constraint
标签的id
属性值须要与要起动画效果的View
的id
保持一致,这样Constraint
标签的全部属性都会做用于该View
。Constraint
标签的属性与ConstraintLayout
的属性是一致的,为此,给正方形开始状态增长一些属性,使其位置水平居中,距离顶部50dp
。
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@+id/vStartStatus"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginTop="50dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
</Constraint>
</ConstraintSet>
复制代码
由于id
为start
的ConstraintSet
标签关联到Transition
标签的constraintSetStart
属性,因此它做为动画(目前只有一个动画)的起始状态。而id
为end
的ConstraintSet
标签关联到Transition
标签的constraintSetEnd
属性,因此它将做为动画的结束状态。结束状态咱们将正方形设置水平居中,距离底部50dp
。
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@id/vStartStatus"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginBottom="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
</Constraint>
</ConstraintSet>
复制代码
设置Constraint
标签时记得设置layout_width
与layout_height
,否则是看不到正方形的。
Transition
标签已经拥有开始和结束状态了,就差触发动画开始的操做了。给Transition
标签增长onClick
子标签,表示点击触发动画。onClick
标签增长clickAction
属性,值为toggle
,表示重复点击时,动画循环效果;增长targetId
属性,值为@id/vStartStatus
,表示点击正方形视图触发过渡动画。<Transition
app:constraintSetEnd="@id/end"
app:constraintSetStart="@+id/start">
<OnClick
app:clickAction="toggle"
app:targetId="@id/vStartStatus" />
</Transition>
复制代码
此时activity_motion_scene.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"
app:defaultDuration="500">
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@+id/vStartStatus"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginTop="50dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@id/vStartStatus"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginBottom="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
</Constraint>
</ConstraintSet>
<Transition
app:constraintSetEnd="@id/end"
app:constraintSetStart="@+id/start">
<OnClick
app:clickAction="toggle"
app:targetId="@id/vStartStatus" />
</Transition>
</MotionScene>
复制代码
效果图
下面讲介绍一些标签的属性与效果。
Transition
标签主要用来指定Motion场景中一个或多个动画。即关联到动画对应的各类状态和用户交互动做。和过渡动画是大同小异的。
经常使用属性:
constraintSetStart
:指定动画初始状态;
constraintSetEnd
:指定动画结束状态;
duration
:指定动画时长;
autoTransiton
:是否自动开启动画。取值有:animateToStart
过渡到初始状态、animateToEnd
过渡到结束状态、jumpToEnd
跳到结束状态、jumpToStart
跳到初始状态、none
不开始状态。默认状况下是none
,当设为其余值时,不用和用户交互即自动开启动画。
motionInterpolator
:插值器。取值有:linear
线性、bounce
弹簧、easeIn
淡入、easeOut
淡出、easeInOut
淡入淡出;
transitionDisable
:容许动画功能。取值:false
和true
;
layoutDuringTransition
:动画过程当中,MotionLayout
子View
调用reqeustLayout
,是否作出响应。取值honorRequest
响应、ignoreRequest
忽略;(beta 4)
Transition
标签经过一些子标签,实现与用户交互的行为。例如上文的OnClick
子标签表示用户的点击行为。
OnClick
标签:点击场景中某个视图,开始动画效果。OnSwipe
标签:表示在布局上滑动时要执行的操做。因为我的能力有限,一些属性不能准备表达。在上文中,默认状况下过渡动画Transition
标签会关联一个开始状态和一个结束状态的TransitionSet
标签。但咱们知道Transition
标签不只能够建立初始状态和结束状态,还能够建立中间状态。这些中间状态则由关键帧来构成,以实现更复杂的动画效果。
KeyFrameSet
标签:用来指定某个中间状态的位置和属性。其实和过渡动画的关键帧是同样的概念。KeyFrameSet
标签含有KeyPosition
和KeyAttribute
两个子标签,这些共同构成过渡动画过程当中某特殊状态的位置和属性。
位置关键帧
KeyPosition
标签: 用来定义整个运动动画中某个状态的位置,相比于静态的TransitionSet
标签来讲,更加灵活。
framePosition
:当前关键帧的位置,把整个运动动画分红100个位置,取值0到99,那么初始状态的位置就是0,结束状态就是99。
keyPositionType
:参考坐标系的选择,决定了percentX
和percentY
属性取值的结果。
取值:parentRelative
表示坐标系基于父视图。例如在开头的demo,加上下面的关键帧:
<KeyFrameSet>
<KeyPosition
app:percentY="0.5"
app:framePosition="50"
app:motionTarget="@id/vStartStatus"
app:keyPositionType="parentRelative"
app:percentX="0.25" />
</KeyFrameSet>
复制代码
代码定义了运动动画过程的中间位置framePosition="50"
,参考系选择了相对父视图坐标keyPositionType="parentRelative"
。因为父视图是全屏,因此坐标系原点在屏幕的左上角,percentY="0.5"
和percentX="0.25"
则表示正方形在父视图高度的1/2,宽度1/4的位置。
效果图
keyPositionType
属性改成
deltaRelative
,即坐标系选择参照整个过渡动画的位置,那么起始状态的位置就是原点(0,0),结束状态的位置就是终点(1,1)。 这里因为原点和终点在x轴上的距离是0,因此
percentX="0.25"
是没有效果的。
效果图:
将keyPositionType
属性改成pathRelative
,即坐标系选择参照整个运动路径,即起始和终点的直线距离构成X轴,此时y轴就有正负之分,表示在X轴的左边仍是右边。x轴和y轴的长度都是等于路径的长度。
例如代码以下:
<KeyFrameSet>
<KeyPosition
app:framePosition="50"
app:percentX="0.5"
app:percentY="0.1"
app:keyPositionType="pathRelative"
app:motionTarget="@id/vStartStatus" />
</KeyFrameSet>
复制代码
效果图:
percentY
改成
-1
:
<KeyFrameSet>
<KeyPosition
app:framePosition="50"
app:percentX="0.5"
app:percentY="-0.1"
app:keyPositionType="pathRelative"
app:motionTarget="@id/vStartStatus" />
</KeyFrameSet>
复制代码
效果图:
percentWidth
和percentHeight
属性表示视图自身大小,若是整个动画过程当中,视图大小不存在变化,是没有效果的。例如文章开始的demo就是没有效果的,能够将正方形在起始状态和结束状态的大小改成不一致,就能够看到效果。percentWidth
和percentHeight
属性会致使sizePercent
属性失效。
属性关键帧
KeyAttribute
相对于位置关键帧,属性关键帧更注重的是属性,而不是某位置。例如常见的位移、旋转动画。 属性有:
framePosition
关键帧位置motionTarget
关联视图IdtransitionEasing
动画速度curveFit
选择基于直线的路径或基于单一速率的路径motionProgress
设置动画进度android:alpha
透明度android:elevation
阴影,注意SDK版本android:rotation
旋转android:rotationX
绕X轴旋转"android:rotationY"
绕Y轴旋转android:transformPivotX
旋转或缩放的中心点X坐标android:transformPivotY
旋转或缩放的中心点Y坐标transitionPathRotate
android:scaleX"
X轴缩放android:scaleY"
Y轴缩放android:translationX
X轴平移android:translationY
Y轴平移android:translationZ
X轴平移若是以上属性不够,也能够经过添加CustomAttribute
子标签实现本身属性,跟属性动画自定属性是同个概念。
自定义属性
CustomAttribute
标签必须经过attributeName
属性指定一个属性名。支持下类型的属性。
customColorValue
颜色值类型customColorDrawableValue
颜色值的Drawable类型customIntegerValue
int类型customFloatValue
float类型customStringValue
String类型customDimension
尺寸类型customPixelDimension
Pixel尺寸类型customBoolean
Boolean 类型到这里,Transition
标签和其子标签、相关属性基本就介绍完了。
ConstraintSet
约束集主要用来定义多个属性集合,并经过id被Transition
标签引用,做为运动动画过程的起始或结束状态。
Constraint标签
子标签Constraint
用来该状态某个View
的相关约束属性,约束属性支持ConstraintLayout
布局的全部属性+上文提到的自定义属性。或者经过组织Layout
、PropertySet
、Transform
、Motion
、CustomAttribute
等子标签,关于这些子标签,感兴趣能够参阅官方文档
【系列好文推荐】
【参考文章】
【点赞,方便往后查阅;点赞,码字不易】