ConstraintLayout&MotionLayout

ConstraintLayout

顾名思义,约束布局———在constraintLayout下的子控件都会受到外来的“力”,从而确定该子控件的位置。


一、constraintLayout来自支持库,所以要想使用先要在gradle中引入

repositories {
    google()
}
dependencies {
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
}

二、“力”的发出者,作用点,作用方向
  举个例子:

app:layout_constraintLeft_toLeftOf="parent"

parent:发出者是parent;
constraintLeft:作用在该子控件的左侧;
toLeftOf    constraintLeft:从parent的左侧拉住该子控件的左侧。
 

“力”的发出者:
parent:包含此控件的constraintLayout;
@+id/button8:其他子控件;
@+id/guideline3:准线———一条用于定位的不可见的线;
举个例子:

    <android.support.constraint.Guideline
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:id="@+id/guideline3"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />

android:orientation="vertical":这是一条从上至下的准线;
app:layout_constraintGuide_percent="0.5":该准线位于constraintLayout的50%处;
这条准线从中间把constraintLayout分成左右两半;
@+id/barrier7:屏障———由几个控件组成的一道不可见的“墙”;
举个例子:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:text="short"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:text="longlonglong"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView1" />

    <android.support.constraint.Barrier
        android:id="@+id/barrier7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="end"
        app:constraint_referenced_ids="textView2,textView1" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:text="@string/lake_discription"这里很长一段
        app:layout_constraintStart_toEndOf="@+id/barrier7"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

app:constraint_referenced_ids="textView2,textView1":由 textView2,textView1组成的“墙”;
app:barrierDirection="end":在textView2,textView1的尾部(一般指右侧);
app:layout_constraintStart_toEndOf="@+id/barrier7":这个墙的尾部(写toStartOf一样的效果,因为“墙”只是一条线,不分首尾)拉住textView3的头部;
最后效果图:

“力”的方向与作用点: 

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
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf

layout_constraintBaseline_toBaselineOf:文字基准线对齐文字基准线,这个这么理解;
另外:constraintlayout中的app:layout_constraintLeft_toLeftOf="parent"和app:layout_constraintEnd_toEndOf="parent"配合起来用会使布局靠近parent的右侧。


        android:layout_width="wrap_content"                    
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
等价于
        android:layout_width="0dp"//或者wrap_content
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintEnd_toEndOf="parent"

效果图如下:
 

三、“力”的大小与bias:
默认情况下,左右的力是相同大小的,上下的力是相同大小的;
左右居中只需要如下:

                 app:layout_constraintLeft_toLeftOf="parent"
                 app:layout_constraintRight_toRightOf="parent

那么如何更偏左一点,加大左边的力?那不是直接拉到最左边了?假设控件处于一个左右横置的管子中,那么只要减少左边的压强,那么控件就会往左跑。跑到哪里?还是不确定。Google提供了更简单的方法是控件停在需要的位置:

                 app:layout_constraintHorizontal_bias="0.3"
                 app:layout_constraintLeft_toLeftOf="parent"
                 app:layout_constraintRight_toRightOf="parent

app:layout_constraintHorizontal_bias="0.3":该控件会停在左边占空白30%,右侧占空白70%的位置。


四、边距:
和原来一样的边距表示方式:

android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom

另外还提供当某一个方向上的“力”的发出者消失的情况的边距:

layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom

举个例子:

    <Button
        android:id="@+id/button4"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:text="button4"
        app:layout_constraintRight_toRightOf="parent"/>
    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="10dp"
        android:text="button5"
        app:layout_constraintRight_toLeftOf="@id/button4"
        app:layout_goneMarginRight="110dp"/>

android:layout_marginRight="10dp":button4 visiable或invisiable时button5距离button4 10dp;
app:layout_goneMarginRight="110dp":当button4 gone时button5距离button4变成的点 110dp。
 

五、圆定位:

<Button android:id="@+id/buttonA" ... />
  <Button android:id="@+id/buttonB" ...
      app:layout_constraintCircle="@+id/buttonA"
      app:layout_constraintCircleRadius="100dp"
      app:layout_constraintCircleAngle="45" />

效果如下:

 

六、控件的大小:
和原来一样的方式设置最大最小宽高

android:minWidth
android:minHeight
android:maxWidth
android:maxHeight

设置宽高的三种方式:
具体尺寸;
WRAP_CONTENT:包含内容大小;
0dp:相当于原来的MATCH_CONSTRAINT。
 

使用比例设置宽高:
如下两例,高将根据宽的长度来设置:

         <Button android:layout_width="wrap_content"
                   android:layout_height="0dp"
                   app:layout_constraintDimensionRatio="1:1" />
         <Button android:layout_width="0dp"
                   android:layout_height="0dp"
                   app:layout_constraintDimensionRatio="H,16:9"
                   app:layout_constraintBottom_toBottomOf="parent"
                   app:layout_constraintTop_toTopOf="parent"/>

七、链(chain)
几个在横向或者竖向上相邻的两两控件互相作用的几个控件构成链。

链头是就是最左边或者最上面的那个控件,关于链的整体属性设置都需要在链头中设置,在其他链结中设置无效。
 

 chainStyle决定链中元素互相之间的位置关系
spread:默认方式,链结会舒展开;
spread_inside:链结会舒展,链的两头会一直舒展到parent边;
packed:链结会聚在一起。
图示,以及相应代码如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/button2"
        app:layout_constraintHorizontal_chainStyle="spread"/>
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@+id/button1"
        app:layout_constraintRight_toLeftOf="@+id/button3"/>
    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@+id/button2"
        app:layout_constraintRight_toRightOf="parent"/>
    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/button5"
        app:layout_constraintHorizontal_chainStyle="spread_inside"/>
    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button1"
        app:layout_constraintLeft_toRightOf="@+id/button4"
        app:layout_constraintRight_toLeftOf="@+id/button6"/>
    <Button
        android:id="@+id/button6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button1"
        app:layout_constraintLeft_toRightOf="@+id/button5"
        app:layout_constraintRight_toRightOf="parent"/>
    <Button
        android:id="@+id/button7"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button4"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/button8"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintHorizontal_weight="1"/>
    <Button
        android:id="@+id/button8"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button4"
        app:layout_constraintLeft_toRightOf="@+id/button7"
        app:layout_constraintRight_toLeftOf="@+id/button9"
        app:layout_constraintHorizontal_weight="2"/>
    <Button
        android:id="@+id/button9"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button4"
        app:layout_constraintLeft_toRightOf="@+id/button8"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintHorizontal_weight="3"/>
    <Button
        android:id="@+id/button10"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button7"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/button11"
        app:layout_constraintHorizontal_chainStyle="packed"/>
    <Button
        android:id="@+id/button11"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button7"
        app:layout_constraintLeft_toRightOf="@+id/button10"
        app:layout_constraintRight_toLeftOf="@+id/button12"/>
    <Button
        android:id="@+id/button12"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button7"
        app:layout_constraintLeft_toRightOf="@+id/button11"
        app:layout_constraintRight_toRightOf="parent"/>
    <Button
        android:id="@+id/button13"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button10"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/button14"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintHorizontal_bias="0.3"/>
    <Button
        android:id="@+id/button14"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button10"
        app:layout_constraintLeft_toRightOf="@+id/button13"
        app:layout_constraintRight_toLeftOf="@+id/button15"/>
    <Button
        android:id="@+id/button15"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button10"
        app:layout_constraintLeft_toRightOf="@+id/button14"
        app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>

 MotionLayout

motionlayout是一种根据动作进行动画的布局。
一、motionlayout是constraintlayout支持库2.0版本推出的,想要使用需要先引入:

    implementation 'com.android.support.constraint:constraint-layout:2.0.0-alpha2'

二、所需元素:
以MotionLayout为根布局指定需要进行动画的布局;
使用app:layoutDescription="@xml/scene_01"指定动画文件;
在xml文件夹下新建MotionScene为根节点的动画文件;
举个例子:

<?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_02"
    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>
<?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">
        <OnSwipe
            motion:dragDirection="dragRight"
            motion:touchAnchorId="@id/button" />
    </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" />
    </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" />
    </ConstraintSet>

</MotionScene>


三、MotionScene文件 
Transition节点:motionScene文件必须包含的节点,使用motion:constraintSetStart和motion:constraintSetEnd来指定动画的第一帧和最后一帧。

        motion:constraintSetStart="@layout/motion_01_cl_start"
        motion:constraintSetEnd="@layout/motion_01_cl_end"

可以指定第一帧和最后一帧在layout文件下;

        motion:constraintSetEnd="@+id/end"
        motion:constraintSetStart="@+id/start"

也可以指定第一帧和最后一帧在对应id的ConstraintSet节点下。
 

ConstraintSet节点:节点下包含多个Constraint节点,每个Constraint节点代表对应id的控件在第一帧或最后一帧的位置。
Constraint节点除了指定位置大小信息外,可以使用

            android:alpha="1.0"
            android:scaleX="1.1"
            android:scaleY="1.1"
            android:rotation="-45.0"
            android:translationY="8dp"

指定控件透明度、放大倍数、旋转角度、移动距离,还可以

            <CustomAttribute
                motion:attributeName="BackgroundColor"
                motion:customColorValue="#9999FF" />

通过CustomAttribute节点指定控件的属性。
来个例子:

<?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">
        <OnSwipe
            motion:dragDirection="dragRight"
            motion:touchAnchorId="@id/button" />
    </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="@color/colorAccent" />
        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@id/button"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginEnd="8dp"
            android:alpha="1.0"
            android:scaleX="1.1"
            android:scaleY="1.1"
            android:rotation="-45.0"
            android:translationY="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>

OnSwipe节点:使用motion:dragDirection="dragLeft"指定动作方向(动作需要在motionLayout布局中进行),使用motion:touchAnchorId="@id/button"指定需要动画的控件(多个需要动画的控件时任意选择一个id)。

        <OnSwipe
            motion:touchAnchorId="@+id/sublabel"
            motion:dragDirection="dragUp" />

KeyFrameSet节点:指定中间关键帧,其下有KeyPosition、KeyAttribute、KeyCycle三种节点分别用来指定控件的位置、属性、三角函数式位置。但KeyCycle不能与KeyPosition不能同时使用(同时使用只有KeyPosition生效)。

        <KeyFrameSet>
            <KeyAttribute
                android:scaleX="2"
                android:scaleY="2"
                android:rotation="-45"
                motion:framePosition="50"
                motion:target="@id/button" />
            <KeyPosition
                motion:keyPositionType="pathRelative"
                motion:percentY="-0.3"
                motion:framePosition="50"
                motion:target="@id/button"/>
        </KeyFrameSet>
        <KeyFrameSet>
            <KeyCycle
                android:translationY="50dp"
                motion:framePosition="100"
                motion:target="@id/button"
                motion:waveOffset="0"
                motion:wavePeriod="0"
                motion:waveShape="sin" />
            <KeyCycle
                android:translationY="50dp"
                motion:framePosition="50"
                motion:target="@id/button"
                motion:waveOffset="0"
                motion:wavePeriod="1"
                motion:waveShape="sin" />
            <KeyCycle
                android:translationY="50dp"
                motion:framePosition="0"
                motion:target="@id/button"
                motion:waveOffset="0"
                motion:wavePeriod="0"
                motion:waveShape="sin" />
        </KeyFrameSet>

四、ImageFilterView
android.support.constraint.utils.ImageFilterView控件是一个图片渐变动画控件;
他有两种形式;
1、使用android:src="@drawable/roard"、app:altSrc="@drawable/hoford"设置两张图片;

<?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_04"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

</android.support.constraint.motion.MotionLayout>

同时使用Crossfade属性指定第一帧或最后一帧的图片是src还是altSrc(0为src图片,1为altSrc图片)。

            <CustomAttribute
                motion:attributeName="Crossfade"
                motion:customFloatValue="0" />

2、使用一张图片只指定src;
同时使用Saturation属性指定第一帧或者最后一帧的图片是黑白的还是彩色的(0为黑白的,1为彩色的)。

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

五、使用其他动作来指挥动画
1、只有motionLayout才能只能指挥动画,我们根布局必须使用motionLayout或者其子类,所以我们新建一个类继承motionLayout;
2、需要什么样的动作,就要继承该动作的接口,例如抽屉的抽拉动作接口DrawerLayout.DrawerListener,并在onAttachedToWindow时就监听这个动作;
3、使用该动作的进度设置motionLayout的进度,调用setProgress()方法。
举个例子:

import android.content.Context;
import android.support.constraint.motion.MotionLayout;
import android.support.design.widget.AppBarLayout;
import android.util.AttributeSet;

public class CollapsibleToolbar extends MotionLayout implements AppBarLayout.OnOffsetChangedListener {
    public CollapsibleToolbar(Context context) {
        super(context);
    }

    public CollapsibleToolbar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CollapsibleToolbar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
        setProgress(-(float) i / (float) (appBarLayout.getTotalScrollRange()));
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        ((AppBarLayout) getParent()).addOnOffsetChangedListener(this);
    }
}

六、ConstraintHelper
放置在MotionLayout中可以监听并操作子控件;
使用app:constraint_referenced_ids="imageView9"指示需要监听操作的控件:

    <com.msz.motionlayout.helpers.ExampleFlyinBounceHelper
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:constraint_referenced_ids="imageView9"/>

自定义ConstraintHelper重写updatePreLayout、updatePostLayout、updatePostMeasure、updatePostConstraints:

import android.animation.ObjectAnimator;
import android.content.Context;
import android.support.constraint.ConstraintHelper;
import android.support.constraint.ConstraintLayout;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.BounceInterpolator;

public class ExampleFlyinBounceHelper extends ConstraintHelper {
    protected ConstraintLayout mContainer;

    public ExampleFlyinBounceHelper(Context context) {
        super(context);
    }

    public ExampleFlyinBounceHelper(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ExampleFlyinBounceHelper(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void updatePreLayout(ConstraintLayout container) {
        if (mContainer!=container) {
            View[] views = getViews(container);
            for (int i = 0; i < mCount; i++) {
                View view = views[i];
                ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", - 2000, 0).setDuration(1000);
                animator.setInterpolator(new BounceInterpolator());
                animator.start();
            }
        }
        mContainer = container;
    }
}

这里进行了一个界面初始化时弹性移动的动画。
 

七、LottieAnimationView
可以使用MotionLayout动作的进度控制LottieAnimationView动画的进度。
1、先引入三方包:

    implementation 'com.airbnb.android:lottie:2.5.1'

2、使用LottieAnimationView控件并指定app:lottie_rawRes="@raw/walkthrough"

    <com.airbnb.lottie.LottieAnimationView
        android:id="@+id/animation_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:lottie_rawRes="@raw/walkthrough"/>

关于Lottie动画的制作与更多使用,可以参考https://airbnb.design/lottie/     https://www.jianshu.com/p/d0f4c823fa06
https://github.com/airbnb/lottie-android
关于VectorDrawables的制作与使用,可以参考https://jingyan.baidu.com/article/7f766daf8775df4101e1d0e1.html
https://developer.android.com/guide/topics/graphics/vector-drawable-resources

更多参考:https://github.com/googlesamples/android-ConstraintLayoutExamples
https://github.com/1qu212/androidMotionLayoutExamplesmaster
https://developer.android.com/reference/android/support/constraint/ConstraintLayout
https://developer.android.com/reference/android/support/constraint/motion/MotionLayout

猜你喜欢

转载自blog.csdn.net/tz_1qu212/article/details/82462512
今日推荐