文章目录

    • 自定义属性
    • ImageFilterView (1/2)
    • ImageFilterView (2/2)
    • 关键帧
    • Keyframe (1/2), 位置
    • Keyframe (1/2), 属性
    • 结论

有关 Android新控件MotionLayout介绍(一)。今天主要是来看第二章。
主要是通过一系列包括自定义属性、图片操作和关键帧来描绘一下MotionLayout的特征。
原文地址为: https://medium.com/google-developers/introduction-to-motionlayout-part-ii-a31acc084f59

自定义属性

在上一篇文章中我们创建了独立的MotionScene,我们可以通过它来实现我们指定的属性转换,当然这种属性并不仅仅是指位置上的。
Android新控件MotionLayout介绍(二)_第1张图片
实际上,原始的ConstraintSet 只封装了layout布局规则;但是对于丰富的动画,我们经常需要转换其他(并非布局规则)的东西(举个例子,我需要改变背景颜色)。在ConstraintLayout 2.0中,ConstraintSet也可以存储自定义属性的状态。在接下来的运动情景中,我们的背景颜色是可以切换的。
Android新控件MotionLayout介绍(二)_第2张图片
很显然,在以前要实现这种动画,你必须在代码中实现。但是现在你在XML中指定相关的自定义直接指定就行了。

<Constraint    android:id="@+id/button" ...>    <CustomAttribute        motion:attributeName="backgroundColor"        motion:customColorValue="#D81B60"/>Constraint>

我们来看一下XML中的代码怎么写:

<?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"        motion:interpolator="linear">        <OnSwipe            motion:dragDirection="dragRight"            motion:touchAnchorId="@+id/button"            motion:touchAnchorSide="right" />    Transition>    <ConstraintSet android:id="@+id/start">        <Constraint            android:id="@+id/button"            android:layout_width="64dp"            android:layout_height="64dp"            android:layout_marginStart="8dp"            motion:layout_constraintBottom_toBottomOf="parent"            motion:layout_constraintStart_toStartOf="parent"            motion:layout_constraintTop_toTopOf="parent">            <CustomAttribute                motion:attributeName="backgroundColor"                motion:customColorValue="#D81B60" />        Constraint>    ConstraintSet>    <ConstraintSet android:id="@+id/end">        <Constraint            android:id="@+id/button"            android:layout_width="64dp"            android:layout_height="64dp"            android:layout_marginEnd="8dp"            motion:layout_constraintBottom_toBottomOf="parent"            motion:layout_constraintEnd_toEndOf="parent"            motion:layout_constraintTop_toTopOf="parent">            <CustomAttribute                motion:attributeName="backgroundColor"                motion:customColorValue="#9999FF" />        Constraint>    ConstraintSet>MotionScene>

自定义属性可以通过属性名指定,但是它必须存在getter/setter方法,就像这种:

  • getter: getName (比如getBackgrounColor)
  • setter: setName (比如setBackgroundColor)

自定义属性的值也必须指定:(不同的类型的值需要不一样的赋值方式)

  • customColorValue --> 针对颜色数据
  • customIntegerValue --> 针对整型数据
  • customFloatValue–> 针对浮点型数据
  • customStringValue–> 针对字符串
  • customDimension–> 针对尺寸
  • customBoolean–> 针对布尔型

最终,当我们定义一个自定义属性时,我们需要在start ConstraintSetend ConstraintSet中同时定义自定义属性和自定义属性值。

ImageFilterView (1/2)

当我们处理比较复杂的转换时,我们经常需要对图片做一些操作,然后将动画作用到它们图片身上。ConstraintLayout 2.0给我们带来了一个非常易用和实用的类:ImageFilterView (继承自AppCompatImageView)。
我们来做一个两张图片相互交换例子,就像下面:
Android新控件MotionLayout介绍(二)_第3张图片
首先我们需要定义一个有图片的MotionLayout文件:

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.motion.MotionLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/motionLayout"    app:layoutDescription="@xml/scene_04"    android:layout_width="match_parent"    android:layout_height="match_parent">    <android.support.constraint.utils.ImageFilterView        android:id="@+id/image"        android:background="@color/colorAccent"        android:src="@drawable/roard"        app:altSrc="@drawable/hoford"        android:layout_width="64dp"        android:layout_height="64dp"/>android.support.constraint.motion.MotionLayout>

其中说明一下:roard.png图片是左侧人物图像,hoford.png图片是右侧人物图像。

与普通的ImageView相比,ImageFilterView多了一个属性:altSrc,(这个属性就是提供了淡入淡出的功能)

<android.support.constraint.image.ImageFilterView    android:id="@+id/image"...    android:src="@drawable/roard"    app:altSrc="@drawable/hoford"/>

在MotionScene文件中,我们可以定义一个淡入淡出的属性:

<?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"        motion:interpolator="linear">        <OnSwipe            motion:dragDirection="dragRight"            motion:touchAnchorId="@+id/image"            motion:touchAnchorSide="right" />    Transition>    <ConstraintSet android:id="@+id/start">        <Constraint            android:id="@+id/image"            android:layout_width="100dp"            android:layout_height="100dp"            android:layout_marginStart="8dp"            motion:layout_constraintBottom_toBottomOf="parent"            motion:layout_constraintStart_toStartOf="parent"            motion:layout_constraintTop_toTopOf="parent">            <CustomAttribute                motion:attributeName="crossfade"                motion:customFloatValue="0" />        Constraint>    ConstraintSet>    <ConstraintSet android:id="@+id/end">        <Constraint            android:id="@+id/image"            android:layout_width="100dp"            android:layout_height="100dp"            android:layout_marginEnd="8dp"            motion:layout_constraintBottom_toBottomOf="parent"            motion:layout_constraintEnd_toEndOf="parent"            motion:layout_constraintTop_toTopOf="parent">            <CustomAttribute                motion:attributeName="crossfade"                motion:customFloatValue="1" />        Constraint>    ConstraintSet>MotionScene>

crossfade是来自ImageFilterView的自身属性,可以参考源码:
Android新控件MotionLayout介绍(二)_第4张图片

ImageFilterView (2/2)

ImageFilterView提供了很多功能:

saturation : 0 = grayscale, 1 = original, 2 = hyper saturated (饱和度 0:灰度 1:原始 2: 超饱和)

contrast : 1 = unchanged, 0 = gray, 2 = high contrast (对比度 1:无改变 0:灰色 2:高对比度)

warmth : 1 = neutral, 2 = warm (red tint), 0.5 = cold (blue tint) (暖色 1:正常的 2:暖色调(偏红色的) 0.5: 冷色调(偏蓝色的))

crossfade (with app:altSrc) 渐入渐出(上面已经说过)

这里有个例子大家展示一下:图片太大,上传不了,我只能压缩一下上传了:(

使用自定义属性来指定图片的饱和度信息,即可完成上面的骚操作:

<CustomAttribute    motion:attributeName="saturation"    motion:customFloatValue="1" />

完整的MotionLayout代码为:

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.motion.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/motionLayout"    app:layoutDescription="@xml/scene_05"    android:layout_width="match_parent"    android:layout_height="match_parent">    <android.support.constraint.utils.ImageFilterView        android:id="@+id/image"        android:src="@drawable/sunset2"        android:scaleType="centerCrop"        android:layout_width="match_parent"        android:layout_height="300dp" />android.support.constraint.motion.MotionLayout>

其中scene_05.xml文件为:

<?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:constraintSetStart="@+id/start"        motion:constraintSetEnd="@+id/end"        motion:duration="1000">        <OnSwipe            motion:touchAnchorId="@+id/image"            motion:touchAnchorSide="top"            motion:dragDirection="dragUp" />    Transition>    <ConstraintSet android:id="@+id/start">        <Constraint            android:id="@+id/image"            android:layout_width="match_parent"            android:layout_height="300dp"            motion:layout_constraintStart_toStartOf="parent"            motion:layout_constraintTop_toTopOf="parent">            <CustomAttribute                motion:attributeName="saturation"                motion:customFloatValue="1" />        Constraint>    ConstraintSet>    <ConstraintSet android:id="@+id/end">        <Constraint            android:id="@+id/image"            android:layout_width="match_parent"            android:layout_height="300dp"            motion:layout_constraintBottom_toBottomOf="parent"            motion:layout_constraintEnd_toEndOf="parent">            <CustomAttribute                motion:attributeName="saturation"                motion:customFloatValue="0" />        Constraint>    ConstraintSet>MotionScene>

关键帧

MotionLayout的一个非常好的想法就是“静止的状态”,它是由ConstraintSets实现的。我们由MotionLayout产生的布局将会适应不同的屏幕大小,本质上来说,MotionLayout就像典型的ConstraintLayout
在有些情况在,你可能需要一个(转换过程中的)中间状态。这个状态不是一直保持的,而是某个过程中需要经历的(我的理解为瞬时状态)。我们可以通过轻量级的实现方案Keyframes来插入两个以上的ConstraintSets

Keyframes(关键帧)可以被应用到位置上或者自定义属性值上。它会让你在某转换的某一个点上指定这种变化的值。

举个例子,如果你想在转换的25%的过程中,组件变成红色;转换50%的时候,组件上移动,就可以使用Keyframes了。

Keyframe (1/2), 位置

这里有好几种方式(pathRelative, deltaRelative, parentRelative) 可以帮助你实现关键帧的位置,每种方式的不同,将会在后面的内容中讲到。
Android新控件MotionLayout介绍(二)_第5张图片
简单快速介绍一下关键帧的位置,这里我们指定一下在转换的50%时,目标view移动到屏幕的25%的位置。

<Transition ...>    <KeyFrameSet>        <KeyPosition            motion:keyPositionType="parentRelative"            motion:percentY="0.25"            motion:framePosition="50"            motion:target="@+id/button"/>    KeyFrameSet>Transition>

结果如下:
Android新控件MotionLayout介绍(二)_第6张图片
简单的MotionLayout代码如下:

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.motion.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/motionLayout"    app:layoutDescription="@xml/scene_06"    android:layout_width="match_parent"    android:layout_height="match_parent">    <View        android:id="@+id/button"        android:background="@color/colorAccent"        android:layout_width="64dp"        android:layout_height="64dp" />android.support.constraint.motion.MotionLayout>

下面是MotionScene文件了,和以前的MotionScene文件差不多,只是区别在于KeyPosition 元素:

<?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:constraintSetStart="@+id/start"        motion:constraintSetEnd="@+id/end"        motion:duration="1000"        motion:interpolator="linear">        <OnSwipe            motion:touchAnchorId="@+id/button"            motion:touchAnchorSide="right"            motion:dragDirection="dragRight" />        <KeyFrameSet>            <KeyPosition                motion:keyPositionType="parentRelative"                motion:percentY="0.25"                motion:framePosition="50"                motion:target="@+id/button"/>        KeyFrameSet>    Transition>    <ConstraintSet android:id="@+id/start">        <Constraint            android:id="@+id/button"            android:layout_width="64dp"            android:layout_height="64dp"            android:layout_marginStart="8dp"            motion:layout_constraintBottom_toBottomOf="parent"            motion:layout_constraintStart_toStartOf="parent"            motion:layout_constraintTop_toTopOf="parent">            <CustomAttribute                motion:attributeName="backgroundColor"                motion:customColorValue="#D81B60"/>        Constraint>    ConstraintSet>    <ConstraintSet android:id="@+id/end">        <Constraint            android:id="@+id/button"            android:layout_width="64dp"            android:layout_height="64dp"            android:layout_marginEnd="8dp"            motion:layout_constraintBottom_toBottomOf="parent"            motion:layout_constraintEnd_toEndOf="parent"            motion:layout_constraintTop_toTopOf="parent">            <CustomAttribute                motion:attributeName="backgroundColor"                motion:customColorValue="#9999FF"/>        Constraint>    ConstraintSet>MotionScene>

Keyframe (1/2), 属性

和关键帧位置很相似,我们可以使用KeyAttribute在转换中来指定属性。
Android新控件MotionLayout介绍(二)_第7张图片
举个例子,我们想指定当前对象在转换的50%的时候,可以放大2倍和旋转45度,就像下面这种:

我们可以在keyFrameSet中使用KeyAttribute 属性了:

<KeyFrameSet>    <KeyAttribute        android:scaleX="2"        android:scaleY="2"        android:rotation="-45"        motion:framePosition="50"        motion:target="@id/button" />KeyFrameSet>

Motionlayout文件上面的例子中相同,在MotionScene文件中不同点就是KeyFrameSet中多了一个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:constraintSetStart="@+id/start"        motion:constraintSetEnd="@+id/end"        motion:duration="1000"        motion:interpolator="linear">        <OnSwipe            motion:touchAnchorId="@+id/button"            motion:touchAnchorSide="right"            motion:dragDirection="dragRight" />        <KeyFrameSet>            <KeyAttribute                android:scaleX="2"                android:scaleY="2"                android:rotation="-45"                motion:framePosition="50"                motion:target="@id/button" />            <KeyPosition                motion:keyPositionType="screenRelative"                motion:percentY="0.2"                motion:framePosition="50"                motion:target="@id/button"/>        KeyFrameSet>    Transition>    <ConstraintSet android:id="@+id/start">        <Constraint            android:id="@+id/button"            android:layout_width="64dp"            android:layout_height="64dp"            android:layout_marginStart="8dp"            motion:layout_constraintBottom_toBottomOf="parent"            motion:layout_constraintStart_toStartOf="parent"            motion:layout_constraintTop_toTopOf="parent">            <CustomAttribute                motion:attributeName="backgroundColor"                motion:customColorValue="#D81B60"/>        Constraint>    ConstraintSet>    <ConstraintSet android:id="@+id/end">        <Constraint            android:id="@+id/button"            android:layout_width="64dp"            android:layout_height="64dp"            android:layout_marginEnd="8dp"            motion:layout_constraintBottom_toBottomOf="parent"            motion:layout_constraintEnd_toEndOf="parent"            motion:layout_constraintTop_toTopOf="parent">            <CustomAttribute                motion:attributeName="backgroundColor"                motion:customColorValue="#9999FF"/>        Constraint>    ConstraintSet>MotionScene>

结论

这篇文章主要阐述了MotionLayout的比较高级的几个功能,使用自定义属性和关键帧可以创建更多引人注目的动画。
本篇源代码都在 https://github.com/googlesamples/android-ConstraintLayoutExamples。
翻译的不好,请多见谅:)
如果你喜欢,请给我一个赞。

更多相关文章

  1. 安卓课程六 android常用布局属性的介绍
  2. shape属性大全
  3. Android中简单实现选择图片并裁剪
  4. Shape的相关属性详解
  5. Android--shape-指定图形的corners、gradient、padding、size、s
  6. Android基于tess-two的离线身份证等图片文字识别
  7. Android把Bitmap保存为bmp图片
  8. Android 添加系统设置属性
  9. android中处理图片成圆角

随机推荐

  1. Android(安卓)自定义dialog(封装好的)
  2. ArcGis for Android(安卓)10.2.8个人整理
  3. [置顶] Android(安卓)GridView宫格视图
  4. Android(安卓)G1的nand分区情况
  5. Android简单实现BroadCastReceiver广播机
  6. Android(安卓)CoordinatorLayout+AppBarL
  7. 说说 Android(安卓)中的通知(Notification
  8. android图形图像函数汇集
  9. 关于android中操作sim卡联系人的相关内容
  10. 【android】手把手轻松集成微信支付