android MotionLayout从入门到实战..
Posted android超级兵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android MotionLayout从入门到实战..相关的知识,希望对你有一定的参考价值。
android MotionLayout一篇带你了解最新android动画布局!
环境
- system : macOS
- android studio : 4.1.3
- constraintLayout : 2.0.4
- gradle : gradle-6.7.1-bin
- kotlin : 1.4.23
你需要知道什么
- MotionLayout 是ConstraintLayout的子类,具有ConstraintLayout所有功能
implementation ‘androidx.constraintlayout:constraintlayout:2.0.4’
- 使用as预览MotionLayout, as版本必须 >= 4.0
使用 MotionLayout 创建动画
将原ConstraintLayout转换为MotionLayout 布局
转换之后:
可以看出,这里定义了一个Button,如果说在ConstraintLayout,这样写会有警告,让约束起来,但是这里并没有
没有的原因是因为定义了MotionLayout的layoutDescription属性,需要在layoutDescription属性中写
点击动画[OnClick]
onClick#clickAction说明:
类型 | 说明 | 效果图 |
---|---|---|
motion:clickAction=“toggle” | 反转 | |
motion:clickAction=“transitionToEnd” | 动画到第二个 | |
motion:clickAction=“jumpToEnd” | 不添加动画直接结束 | |
motion:clickAction=“jumpToStart” | 不添加动画到开始 | 见名之意… |
motion:clickAction=“transitionToStart” | 添加动画到 | 见名之意… |
多个view一起联动
例如这样:
效果图:
手指拖动 [OnSwipe]
参数介绍:
- motion:touchAnchorId 指的是您可以滑动并拖动的视图。
- motion:touchAnchorSide 表示我们从右侧拖动视图。
- motion:dragDirection 表示拖动的进度方向。
例如,motion:dragDirection=“dragRight” 表示当您向右拖动时,进度会增加。
效果图:
辅助工具
motionLayout默认会自带调试工具.
说明表:
状态 | 说明 | 效果图 |
---|---|---|
app:motionDebug=“SHOW_ALL” | 辅助线和进度显示 | |
app:motionDebug=“SHOW_PATH” | 辅助线显示 | |
app:motionDebug=“SHOW_PROGRESS” | 进度显示 |
官方说明图:
- 圆圈代表一个视图的开始或结束位置。
- 线条代表一个视图的路径。
- 菱形代表KeyPosition修改路径。
还有一种使用视图的方式来调试:
修改路径(KeyPosition)
修改路径可以通过右侧可视化工具来进行:
详解图:
详解1 | 详解2 |
---|---|
再来看看自动生成的代码:
KeyPosition参数详解:
- motion:motionTarget="@+id/button" 需要移动轨迹的view
- motion:framePosition="[0-100]" framePosition是一个介于 0 和 100 之间的数字。它定义了在动画KeyPosition中的应用时间,1 表示 1% 的动画,99 表示 99% 的动画
- motion:keyPositionType=’’ ‘’ keyPositionType这是如何KeyPosition修改路径。它可以是
parentRelative
,pathRelative
,或deltaRelative
- percentX | percentY是修改路径的量framePosition(值介于 0.0 和 1.0 之间,允许负值和值 >1)
这里motion:keyPositionType=’’ ''参数解释一下:
类型 | 说明 | 坐标系 | 效果图 |
---|---|---|---|
pathRelative | 它与其他两个完全不同,因为 X 轴从头到尾遵循运动路径。所以,(0,0)是的起始位置,并且(1,0)是结束位置。 | ||
deltaRelative | deltaRelative也是“相对变化”的一种说法。在deltaRelative坐标中(0,0)是视图的起始位置,(1,1)是结束位置。X 轴和 Y 轴与屏幕对齐。X 轴在屏幕上始终是水平的,Y 轴在屏幕上始终是垂直的。与 相比parentRelative,主要区别在于坐标仅描述了视图将在其中移动的屏幕部分。 | 效果和pathRelative类似,不做演示 | |
parentRelative | parentRelative使用相同的坐标系作为屏幕。它定义(0, 0)在整个 的左上角MotionLayout和(1, 1)右下角。 |
parentRelative:
这里设置了4个点
分别为:
假设现在移动起始点1
,deltaRelative会以开始点
和起始点2
来构建一个‘贝塞尔环境’
来生成对应的路径,这里和pathRelative效果类似但也有不同之处!
pathRelative和deltaRelative的区别:
- pathRelative不需要依靠起始点和结束点就可以拖动
- deltaRelative 起始点和结束点在同一x轴上会导致动画路径不按照贝塞尔路径执行.而是执行一条直线.
如图所示:
类型 | 说明 | 效果图 |
---|---|---|
deltaRelative | 需要依靠起始点和结束点 | |
pathRelative 或 parentRelative | 不需要依靠起始点和结束点 |
最终效果长这样:
效果都一样,就只放一个喽,需要的请下载源码观看…
KeyPosition配合pathMotionArc进阶
pathMotionArc见名之意就知道是用来画弧形的.
先来看pathMotionArc简单的例子:
可以看出,想要画一条优雅的弧线很简单,只需要在开始点设置 motion:pathMotionArc="startHorizontal"
即可
⚠️:motion:pathMotionArc是需要2个点才生效的,默认是开始点
和结束点
如何设置多个点呢?例如这样:
也可以设置两个弧形的比例大小等
位置坐标说明:
pathMotionArc类型介绍:
- startVertical 向下的弧形
- startHorizontal 向上的弧形
- none 直线
- flip 和上一个点如果上一个点是startVertical,那么当前就是startHorizontal,可以理解为反转
类型 | 说明 | 效果图 |
---|---|---|
效果一 | 开始点: motion:pathMotionArc="startVertical" 起始点1: motion:pathMotionArc="startHorizontal" 起始点2: motion:pathMotionArc=“startHorizontal” | |
效果二 | 开始点: motion:pathMotionArc="startVertical" 起始点1: motion:pathMotionArc="none" 起始点2: motion:pathMotionArc=“startHorizontal” | |
效果三 | 开始点: motion:pathMotionArc="startVertical" 起始点1: motion:pathMotionArc="startVertical" 起始点2: motion:pathMotionArc=“flip” |
效果一
,效果二
和效果三的代码高度重复,这里就只贴一下效果三
的代码:
效果三
代码:
<?xml version="1.0" encoding="utf-8"?>
<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="1000">
<!-- 点击事件 -->
<OnClick
motion:clickAction="toggle"
motion:targetId="@id/button6" />
<KeyFrameSet>
<!-- 起始点1 和 起始点2设置"关联" -->
<KeyPosition
motion:framePosition="40"
motion:keyPositionType="deltaRelative"
motion:motionTarget="@+id/button6"
motion:pathMotionArc="startVertical"
motion:percentX="0.358"
motion:percentY="0.17" />
<!-- 起始点2 和结束关联 -->
<KeyPosition
motion:framePosition="79"
motion:keyPositionType="deltaRelative"
motion:motionTarget="@+id/button6"
motion:pathMotionArc="flip"
motion:percentX="0.675"
motion:percentY="0.568" />
</KeyFrameSet>
</Transition>
<!-- start -->
<ConstraintSet android:id="@+id/start">
<!-- 开始点 和起始点1设置"关联" -->
<Constraint
android:id="@+id/button6"
android:layout_width="80dp"
android:layout_height="80dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintLeft_toLeftOf="parent"
motion:layout_constraintTop_toTopOf="parent"
motion:pathMotionArc="startVertical" />
</ConstraintSet>
<!-- end -->
<!-- 结束点不设置关联。。 -->
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/button6"
android:layout_width="64dp"
android:layout_height="64dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintRight_toRightOf="parent" />
</ConstraintSet>
</MotionScene>
这里比例也是能改变的,例如这样:
这里还是比较简单的,自己动手试试就懂啦!
改变属性状态(KeyAttribute)
看一眼代码:
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<Transition
motion:constraintSetEnd="@+id/结束了"
motion:constraintSetStart="@id/开始了"
motion:duration="1000">
<KeyFrameSet>
<!-- 改变属性状态 -->
<KeyAttribute
motion:motionTarget="@+id/button7"
motion:framePosition="22"
android:alpha="0.2" />
</KeyFrameSet>
<OnClick
motion:clickAction="toggle"
motion:targetId="@id/button7" />
</Transition>
<!-- 开始 这里也可以定义中文,但是不建议使用。。 -->
<ConstraintSet android:id="@+id/开始了">
<Constraint
android:id="@+id/button7"
android:layout_width="60dp"
android:layout_height="60dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintLeft_toLeftOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<!-- 结束 这里也可以定义中文,但是不建议使用。。-->
<ConstraintSet android:id="@+id/结束了">
<Constraint
android:id="@+id/button7"
android:layout_width="60dp"
android:layout_height="60dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintRight_toRightOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
</MotionScene>
改变alpha的值:
当然也可以设置多个属性,例如这样:
自行探索:
- android:visibility
- android:alpha
- android:elevation
- android:rotation
- android:rotationX
- android:rotationY
- android:scaleX
- android:scaleY
- android:translationX
- android:translationY
- android:translationZ
KeyAttribute配合CustomAttribute设置颜色
- CustomAttribute 常用来设置view颜色的,是KeyAttribute的属性
来看看代码:
<?xml version="1.0" encoding="utf-8"?>
<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="1000">
<!--点击-->
<OnClick
motion:clickAction="toggle"
motion:targetId="@id/imageView8" />
<KeyFrameSet>
<!-- 旋转3圈到 100点 -->
<KeyAttribute
android:rotation="-720"
motion:framePosition="100"
motion:motionTarget="@id/imageView8" />
<!-- 0点 的时候黑色 -->
<KeyAttribute
motion:framePosition="0"
motion:motionTarget="@id/imageView8">
<CustomAttribute
motion:attributeName="colorFilter"
motion:customColorValue="#000000" />
</KeyAttribute>
<!-- 50点的时候红色 -->
<KeyAttribute
motion:framePosition="50"
motion:motionTarget="@id/imageView8">
<CustomAttribute
motion:attributeName="colorFilter"
motion:customColorValue="#E91E63" />
</KeyAttribute>
<!-- 100点的时候黑色 -->
<KeyAttribute
motion:framePosition="100"
motion:motionTarget="@id/imageView8">
<CustomAttribute
motion:attributeName="colorFilter"
motion:customColorValue="#000000" />
</KeyAttribute>
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="@+id/start" ... />
<ConstraintSet android:id="@+id/end" ... />
</MotionScene>
在里面CustomAttribute你必须指定一个attributeName和一个值来设置。
- motion:attributeName是此自定义属性将调用的 setter 的名称。在这个例子中, setColorFilteronDrawable将被调用。
- motion:customColorValue 是名称中注明的类型的自定义值,在此示例中,自定义值是指定的颜色。
自定义值可以具有以下任何类型:- Color
- Integer
- Float
- String
- Dimension
- Boolean
来看效果图就懂了:
设置抖动[KeyCycle]
如何创建:
关键代码:
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start"
motion:duration="1000">
<!--点击-->
<OnClick ... />
<KeyFrameSet>
<!--
motion:waveOffset 添加到属性的偏移值
motion:wavePeriod 要在此区域附近循环的循环数
motion:waveShape="cos"
sin|square|triangle|sawtooth|reverseSawtooth|cos|bounce
正弦| 方形 |三角形 | 锯齿 | 反向锯齿 |cos| 反弹
-->
<KeyCycle
android:alpha="0.5"
android:scaleY="1.2"
android:scaleX="1.2"
motion:framePosition="51"
motion:motionTarget="@+id/imageView8"
motion:waveOffset="2"
motion:wavePeriod="1"
motion:waveShape="sin" />
</KeyFrameSet>
</Transition>
参数介绍:
- motion:waveOffset 添加到属性的偏移值
- motion:wavePeriod 要在此区域附近循环的循环数
- motion:waveShape=“cos”
- sin|square|triangle|sawtooth|reverseSawtooth|cos|bounce
各大类型效果图:
sin | square | triangle | sawtooth | reverseSawtooth | cos | bounce |
---|---|---|---|---|---|---|
正弦 | 方形 | 三角形 | 锯齿 | 反向锯齿 | cos | 反弹 |
设置抖动(KeyTimeCycle)
KeyTimeCycle和KeyCycle使用起来是一样的,参数也是一样的.
有一点不同的是,一般KeyTimeCycle 是三个一起使用,通过 3 个 KeyTimeCycle 定义一个准确的循环关键帧
可以看出,只有在第50帧的时候,会发生改变,因为第50帧的时候设置motion:wavePeriod
为1
- motion:wavePeriod:要在此区域附近循环的循环数
改变控件属性(KeyTrigger)
什么叫改控件属性? 如何控制?
先来看效果:
首先自定义ImageView
,里面就2个方法,show
和hide
class KeyTriggerImageView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) :
AppCompatImageView(context, attrs, defStyleAttr)
// 显示 view
fun show()
visibility = View.VISIBLE
// 隐藏当前 view
fun hide()
visibility = View.GONE
如何使用:
<?xml version="1.0" encoding="utf-8"?>
<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="2000">
<!--点击-->
<OnClick
motion:clickAction="toggle"
motion:targetId="@id/imageView11" />
<KeyFrameSet>
<KeyTrigger
motion:framePosition="0"
motion:motionTarget="@+id/imageView11"
motion:onCross="show" />
<KeyTrigger
motion:framePosition="20"
motion:motionTarget="@+id/imageView11"
motion:onCross="hide" />
<KeyTrigger
motion:framePosition="60"
motion:motionTarget="@+id/imageView11"
motionAndroid新控件MotionLayout介绍
Android新控件之MotionLayout 动画管理布局简单介绍<一>
未调用 Android MotionLayout 过渡侦听器
带有 MotionLayout 的 Android 折叠工具栏 - 当 RecyclerView 为空/不可滚动时禁用运动