MotionLayout is a new class available in the ConstraintLayout 2.0 library to help Android developers manage motion and widget animation in their application.
在使用MotionLayout之前,需要先了解下 ConstraintLayout 布局的使用,ConstraintLayout 完全解析
dependencies {
implementation 'com.android.support.constraint:constraint-layout:2.0.0-beta2'
}
布局文件
<android.support.constraint.motion.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/scene_my_drawer">
<LinearLayout
android:id="@+id/my_drawer"
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" >
<TextView
android:layout_width="match_parent"
android:text="my drawer"
android:layout_height="wrap_content"/>
LinearLayout>
android.support.constraint.motion.MotionLayout>
scene_my_drawer.xml文件
<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/my_drawer"
android:layout_width="300dp"
app:layout_constraintRight_toLeftOf="parent"
android:layout_height="match_parent">
<CustomAttribute
app:attributeName="backgroundColor"
app:customColorValue="#d81b60" />
Constraint>
ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@id/my_drawer"
android:layout_width="300dp"
app:layout_constraintStart_toStartOf="parent"
android:layout_height="match_parent">
<CustomAttribute
app:attributeName="backgroundColor"
app:customColorValue="#9999FF" />
Constraint>
ConstraintSet>
<Transition
app:constraintSetStart="@id/start"
app:constraintSetEnd="@id/end">
<OnSwipe
app:dragDirection="dragRight"
app:touchAnchorId="@id/my_drawer"
app:touchAnchorSide="right" />
Transition>
MotionScene>
运行结果
布局文件
<android.support.constraint.motion.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/scene2">
<ImageView
android:id="@+id/bt_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/timg"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
android.support.constraint.motion.MotionLayout>
scene2.xml文件
<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/bt_start"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginStart="12dp"
android:layout_marginBottom="12dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
Constraint>
ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@id/bt_start"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginBottom="12dp"
android:layout_marginEnd="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
Constraint>
ConstraintSet>
<Transition
app:constraintSetStart="@id/start"
app:duration="2000"
app:constraintSetEnd="@id/end">
<KeyFrameSet>
<KeyPosition
app:framePosition="20"
app:motionTarget="@id/bt_start"
app:keyPositionType="parentRelative"
app:percentX="1"
app:percentY="0.5"/>
<KeyPosition
app:framePosition="40"
app:motionTarget="@id/bt_start"
app:keyPositionType="parentRelative"
app:percentX="0.5"
app:percentY="0.75"/>
<KeyPosition
app:framePosition="60"
app:motionTarget="@id/bt_start"
app:keyPositionType="parentRelative"
app:percentX="0"
app:percentY="0.5"/>
<KeyPosition
app:framePosition="70"
app:motionTarget="@id/bt_start"
app:keyPositionType="parentRelative"
app:percentX="0.25"
app:percentY="0.4"/>
<KeyPosition
app:framePosition="80"
app:motionTarget="@id/bt_start"
app:keyPositionType="parentRelative"
app:percentX="0.5"
app:percentY="0.5"/>
<KeyAttribute
app:motionTarget="@id/bt_start"
android:rotation="-3600"
android:scaleX="2.0"
android:scaleY="2.0"
app:framePosition="50"/>
<KeyAttribute
app:motionTarget="@id/bt_start"
android:rotation="-7200"
app:framePosition="100"/>
KeyFrameSet>
<OnClick
app:clickAction="toggle"
app:targetId="@id/bt_start"/>
Transition>
MotionScene>
运行结果
自定义View
package com.boxing.views;
/**
* Created by liuyuli on 2019-09-02.
*/
public class MyDrawer extends MotionLayout implements DrawerLayout.DrawerListener {
public MyDrawer(Context context) {
super(context);
}
public MyDrawer(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyDrawer(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void onDrawerSlide(@NonNull View view, float slideOffset) {
float progress = slideOffset;
setProgress(progress);
}
@Override
public void onDrawerOpened(@NonNull View view) {
}
@Override
public void onDrawerClosed(@NonNull View view) {
}
@Override
public void onDrawerStateChanged(int i) {
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (getParent() instanceof DrawerLayout) {
DrawerLayout parent = (DrawerLayout) getParent();
parent.addDrawerListener(this);
}
}
}
布局文件
<com.boxing.views.MyDrawer xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@color/colorAccent"
app:layoutDescription="@xml/scene_drawer">
<TextView
android:id="@+id/tv_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="15dp"
android:text="title 1 title 1"
android:textColor="#222"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/tv_2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="15dp"
android:text="title 2 title 2"
android:textColor="#222"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@id/tv_3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_1" />
<TextView
android:id="@+id/tv_3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="15dp"
android:text="title 3 title 3"
android:textColor="#222"
android:textSize="16sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_2" />
com.boxing.views.MyDrawer>
scene_drawer.xml文件
<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/tv_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:rotation="90"
android:translationX="100dp"
app:layout_constraintBottom_toTopOf="@+id/tv_2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintVertical_bias="0"
app:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@+id/tv_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:rotation="90"
app:layout_constraintVertical_bias="0"
android:translationX="100dp"
app:layout_constraintBottom_toTopOf="@id/tv_3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_1" />
<Constraint
android:id="@+id/tv_3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:rotation="90"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0"
android:translationX="100dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_2" />
ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/tv_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/tv_2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@+id/tv_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/tv_3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_1" />
<Constraint
android:id="@+id/tv_3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_2" />
ConstraintSet>
<Transition
app:constraintSetEnd="@id/end"
app:constraintSetStart="@id/start">
Transition>
MotionScene>
运行效果
参考Introduction to MotionLayout (part I)
Introduction to MotionLayout (part II)
Introduction to MotionLayout (part III)