MotionLayout Structure
以下是梳理的整个MotionLayout框架中设计到所有布局配置,点击参见详细的属性解释
Custom attribute
由于原始ConstraintSet
的只封装了layout 规则,为了更丰富的动画,我们需要过渡一些其他的东西(比如在此的 background color). 在ConstraintLayout 2.0中,ConstraintSet
可以保存自定义的属性状态(attribute states),如下所示的变化:
只需要在ConstraintSet
中预设如下自定义属性:
<Constraint
android:id="@+id/button" ...>
<CustomAttribute
motion:attributeName="backgroundColor"
motion:customColorValue="#D81B60"/>
</Constraint
CustomAttribute(自定义属性)通过attributeName被指定,此属性需要满足定义在对象中的 getter/setter 方法,比如:
getter:
getName
(e.g. getBackgroundColor)setter:
setName
(e.g. setBackgroundColor)
属性的值(value)需要被指定为如下的值之一:
customColorValue
customIntegerValue
customFloatValue
customStringValue
customDimension
customBoolean
当指定了自定义属性时,需要同时在 start 和 end ConstraintSet 配置中同时配置,形成一一对应的关系
Keyframe
对于MotionLayout通常的想法就是作为ConstraintSets实现的一个叫 “resting states” 的状态。通过此方式,我们知道结果布局(result layouts)将会被适配到不同的屏幕尺寸上: 实际上,MotionLayout和ContraintLayout表现一致。
在某些情况下,我们可能想要一个中间态(an intermediate state) - (a state to go through, but not a state to stay in)用于穿过,而不是保存??. 可以通过指定操作2个ConstraintSets,但是一个更轻量级的实现方式就是使用 KeyFrames.
KeyFrames 可以被应用于 postion 或者 attributes值中,它们基本上能让你在transition的过程中在某个点指定一个改变
Keyframe - Position
target | View的Id |
---|---|
framePosition | 当前frame位置点[0,100] 插值器的概念(如果是匀速,此点就是当前位置比例) |
type | 此关键帧线性直线的偏差计算方式 {deltaRelative | pathRelative | parentRelative} deltaRelative 是相对两点的直线delta距离 pathRelative 是基于其他配置参数,如percentY. |
transitionEasing | 在当前指定点的ease curve动画曲线(例如:curve(1.0,0,0,1.0)) |
percentX | (float)[start,end]在x坐标上的百分比距离(deltaRelative),pathRelative 则是沿着曲线距离 |
percentY | (float)[start,end]在y坐标(属性中的Y坐标值)上的百分比距离(deltaRelative) pathRelative则表示垂直于线的距离 |
drawPath | Debug中显示的辅助线样式,定义线的值有 {deltaRelative | pathRelative | asConfiged | path | retangles | none} |
sizePercent | 如果View的大小改变,这个用于控制View size变化逻辑(就是表示在该点时,view的size达到了此处定义的size大小) |
curveFit | 线的定义样式:{linear | spline} 直线或者曲线 |
<KeyFrameSet>
<KeyPosition
motion:type="pathRelative"
motion:percentY="-0.25"
motion:percentX="0.7"
motion:framePosition="50"
motion:curveFit="spline"
motion:sizePercent="1"
motion:drawPath="deltaRelative"
motion:target="@id/button"/>
</KeyFrameSet>
上述代码代表帧点的效果如下图所示,此帧在图中粉色点位置,由于interporator是设置的linear,并且设置了 framePosition=”50”, 明显点左边部分的线稀疏,右边紧凑,就是为了保证此粉色点是能代表 “50”点;
percentY=”-0.25” 帧点相对原始位置Y坐标上移动 0.25 Y,因此点在整个基准线上方位置
percentX=”0.7” 针对相对原始位置X坐标移动 0.7 (endX - startX)
curveFit=”spline” 表示运动是曲线,而不是直线(linear)
�
并且可以通过Android studio design 工具去实时预览效果:
tools:progress 用于调节当前帧的进度
tools:showPaths 用于显示辅助线
Keyframe - Attribute
target | View的 Id |
---|---|
framePosition | 当前frame位置点[0,100] 插值器的概念(如果是匀速,此点就是当前位置比例) |
curveFit | 线的定义样式:{linear | spline} 直线或者曲线 |
transitionEasing | 在当前指定点的ease curve动画曲线(例如:curve(1.0,0,0,1.0)) |
transitionPathRotate | (float) rotate object relative to path taken 相对提供的线旋转对象 |
drawPath | draw the path the layout will animate animate |
progress | call method setProgress(float) on this view (used to talk to nested ConstraintLayouts etc.) |
[standard view attributes] | 标准的android:开头的辅助属性 |
<CustomAttribute> |
通过set方法设置的自定义属性(反射调用) |
<KeyFrameSet>
<KeyAttribute
android:scaleX="2"
android:scaleY="2"
android:rotation="-45"
motion:framePosition="50"
motion:target="@id/button" />
<KeyPosition
motion:type="pathRelative"
motion:percentY="-0.3"
motion:framePosition="50"
motion:target="@id/button"/>
</KeyFrameSet>
在framePosition=”50”时, 旋转-45度(rotation), 并且缩放两倍(scaleX,scaleY)
attributeName | attribute的名字,大小写敏感, “MyAttr” 对应的方法类似setMyAttr(…) |
---|---|
customColorValue | The value is a color looking setMyAttr(int ) |
customIntegerValue | The value is an integer looking setMyAttr(int ) |
customFloatValue | The value is a float looking setMyAttr(float ) |
customStringValue | The value is a String looking setMyAttr(String ) |
customDimension | The value is a dimension looking setMyAttr(float ) |
customBoolean | The value is true or false looking setMyAttr(boolean ) |
Keyframe - Cycle
target | View的 Id |
---|---|
framePosition | 当前frame位置点[0,100] 插值器的概念(如果是匀速,此点就是当前位置比例) |
[Standard View attributes] | A collection of view attributes supported by the system (see below) |
waveShape | 生成波动的形状{sin|square|triangle|sawtooth|reverseSawtooth|cos|bounce} |
wavePeriod | 在此区域内的循环周期数 |
waveOffset | offset value added to the attribute 对应属性的偏移量 |
transitionPathRotate | Cycles applied to rotation relative to the path the view is travelling 暂时不清楚此用法 |
progress | call method setProgress(float) on this view (used to talk to nested ConstraintLayouts etc.) (目前测试没效果) |
<CustomAttribute> |
call a set”name” method via reflection (limited to floats) |
<KeyFrameSet>
<KeyCycle --第一个
android:translationY="50dp"
motion:framePosition="100"
motion:target="@id/button"
motion:waveOffset="0"
motion:wavePeriod="1"
motion:waveShape="square" />
<KeyCycle --第二个
android:translationY="50dp"
motion:framePosition="0"
motion:target="@id/button"
motion:waveOffset="0"
motion:wavePeriod="2"
motion:waveShape="sin" />
</KeyFrameSet>
注意:当KeyFrameSet定义了多个KeyCycle时,只有最后一个定义(按照顺序而和framePostion无关系)的KeyCycle中的 waveShape会应用到整个 KeyFrameSet中(代码亲测):如上代码中,只有 waveShape=”sin” 会应用,而忽略 square的定义
�