前面有篇文章简单介绍了一下ConstraintLayout,如果有不熟的地方,可以自行查看。这里主要介绍一下ConstraintLayout可以实现的动画。
具体什么样的呢? 我们先看一个复杂一点的dome:
这里的ConstraintLayout动画主要是将XML中的代码转化到Java代码中即可,还是标间简单的,只是官方给的文档不多,也不知道自己学的对不对。先一个一个来吧。
首先需要添加一个transition依赖,作用是使ConstraintLayout动画过渡,不然就没有动画的感觉:
implementation 'com.android.support:transition:28.0.0'
先从简单的来,先看一下XML布局:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/id_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/id_tv_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="80dp"
android:layout_marginTop="90dp"
android:background="#952"
android:padding="12dp"
android:text="TextView 1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/id_tv_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginTop="149dp"
android:background="#489"
android:padding="12dp"
android:text="TextView 2"
app:layout_constraintLeft_toRightOf="@id/id_tv_1"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/id_tv_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="160dp"
android:background="#09F"
android:padding="12dp"
android:text="TextView 3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/id_tv_1" />
<Button
android:id="@+id/id_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:text="apply"
android:onClick="apply"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<Button
android:id="@+id/id_btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="reset"
android:onClick="reset"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/id_btn" />
android.support.constraint.ConstraintLayout>
Activity需要准备的是,需要两个ConstraintSet来记录改变的ConstraintLayout规则,大致代码如下:
public class ConstraintActivity extends AppCompatActivity {
private ConstraintLayout constraintLayout;
private ConstraintSet applyConstraintSet = new ConstraintSet();
private ConstraintSet resetConstraintSet = new ConstraintSet();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_constraint);
constraintLayout = findViewById(R.id.id_main);
applyConstraintSet.clone(constraintLayout);
resetConstraintSet.clone(constraintLayout);
}
public void apply(View v) {
//constrainLayout动画过渡
TransitionManager.beginDelayedTransition(constraintLayout);
}
public void reset(View v) {
//复原
TransitionManager.beginDelayedTransition(constraintLayout);
resetConstraintSet.applyTo(constraintLayout);
}
在XML代码中,只需要设置TextView的属性:
app:layout_constraintLeft_toLeftOf="parent"
转成Java代码为:
applyConstraintSet.connect(R.id.id_tv_1,ConstraintSet.START, R.id.id_main, ConstraintSet.START, 0);
但是这个属性在XML代码中,TextView1已经有了,我们只需要改变一下TextView的Margin就行了,
那么基本代码是:
public void apply(View v) {
//constrainLayout动画过渡
TransitionManager.beginDelayedTransition(constraintLayout);
//改变TextView的Margin_START
applyConstraintSet.setMargin(R.id.id_tv_1, ConstraintSet.START, 1);
applyConstraintSet.applyTo(constraintLayout);
}
效果图为:
需要首先需要将View的margin设置为0,因为View如果存在Margin,则会影响View位于中间的操作,然后中间设置使用为centerHorizontally
,基础代码为:
public void apply(View v) {
//constrainLayout动画过渡
TransitionManager.beginDelayedTransition(constraintLayout);
applyConstraintSet.setMargin(R.id.id_tv_1, ConstraintSet.START,0);
applyConstraintSet.setMargin(R.id.id_tv_1, ConstraintSet.END,0);
applyConstraintSet.setMargin(R.id.id_tv_2, ConstraintSet.START,0);
applyConstraintSet.setMargin(R.id.id_tv_2, ConstraintSet.END,0);
applyConstraintSet.setMargin(R.id.id_tv_3, ConstraintSet.START,0);
applyConstraintSet.setMargin(R.id.id_tv_3, ConstraintSet.END,0);
applyConstraintSet.centerHorizontally(R.id.id_tv_1, R.id.id_main);
applyConstraintSet.centerHorizontally(R.id.id_tv_2, R.id.id_main);
applyConstraintSet.centerHorizontally(R.id.id_tv_3, R.id.id_main);
applyConstraintSet.applyTo(constraintLayout);
}
动态图为:
上面的移动到水平中心已经知道了centerHorizontally
,那么竖直的使用:centerVertically
,大致代码:
public void apply(View v) {
//constrainLayout动画过渡
TransitionManager.beginDelayedTransition(constraintLayout);
applyConstraintSet.setMargin(R.id.id_tv_3, ConstraintSet.START,0);
applyConstraintSet.setMargin(R.id.id_tv_3, ConstraintSet.TOP,0);
applyConstraintSet.setMargin(R.id.id_tv_3, ConstraintSet.END,0);
applyConstraintSet.setMargin(R.id.id_tv_3, ConstraintSet.BOTTOM,0);
applyConstraintSet.centerHorizontally(R.id.id_tv_3, R.id.id_main);
applyConstraintSet.centerVertically(R.id.id_tv_3, R.id.id_main);
applyConstraintSet.applyTo(constraintLayout);
}
效果动图为:
修改View的尺寸,应该使用constrainHeight
或者constrainWidth
,代码为:
public void apply(View v) {
//constrainLayout动画过渡
TransitionManager.beginDelayedTransition(constraintLayout);
applyConstraintSet.constrainWidth(R.id.id_tv_1, 500);
applyConstraintSet.constrainHeight(R.id.id_tv_1,500);
applyConstraintSet.constrainWidth(R.id.id_tv_2, 600);
applyConstraintSet.constrainHeight(R.id.id_tv_2,300);
applyConstraintSet.constrainWidth(R.id.id_tv_3, 700);
applyConstraintSet.constrainHeight(R.id.id_tv_3,200);
applyConstraintSet.applyTo(constraintLayout);
}
实现效果为:
基本代码如下:
public void apply(View v) {
//constrainLayout动画过渡
TransitionManager.beginDelayedTransition(constraintLayout);
//设置View为Gone
applyConstraintSet.setVisibility(R.id.id_tv_2,ConstraintSet.GONE);
applyConstraintSet.setVisibility(R.id.id_tv_3,ConstraintSet.GONE);
//将R.id.id_tv_1所有的constraint清除
applyConstraintSet.clear(R.id.id_tv_1);
//与app:layout_constraintLeft_toLeftOf功效一致
applyConstraintSet.connect(R.id.id_tv_1,ConstraintSet.START, R.id.id_main, ConstraintSet.START, 0);
applyConstraintSet.connect(R.id.id_tv_1, ConstraintSet.END, R.id.id_main, ConstraintSet.END,0);
applyConstraintSet.connect(R.id.id_tv_1, ConstraintSet.TOP, R.id.id_main, ConstraintSet.TOP,0);
applyConstraintSet.connect(R.id.id_tv_1, ConstraintSet.BOTTOM, R.id.id_main, ConstraintSet.BOTTOM,0);
applyConstraintSet.applyTo(constraintLayout);
}
或者直接:
applyConstraintSet.constrainWidth(R.id.id_tv_1,DeviceUtils.getDeviceWidth());
applyConstraintSet.constrainHeight(R.id.id_tv_1,DeviceUtils.getDeviceHeight);
结果显示图为:
先来看一下我们需要实现的效果吧:
ConstraintSet.CHAIN_SPREAD | ConstraintSet.CHAIN_SPREAD_INSIDE | ConstraintSet.CHAIN_PACKED |
---|---|---|
这个代码都差不多,其实说白只需要明白XML中代码怎么写,这就容易了:
<TextView
android:id="@+id/id_tv_1"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="#278"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/id_tv_2" />
<TextView
android:id="@+id/id_tv_2"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="#786"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/id_tv_1"
app:layout_constraintRight_toLeftOf="@id/id_tv_3" />
<TextView
android:id="@+id/id_tv_3"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="#d08"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/id_tv_2"
app:layout_constraintRight_toRightOf="parent" />
转成Java代码为:
public void apply(View v) {
//constrainLayout动画过渡
TransitionManager.beginDelayedTransition(constraintLayout);
applyConstraintSet.clear(R.id.id_tv_1);
applyConstraintSet.clear(R.id.id_tv_2);
applyConstraintSet.clear(R.id.id_tv_3);
//R.id.id_tv_1左边与父布局左边对齐
applyConstraintSet.connect(R.id.id_tv_1, ConstraintSet.START, R.id.id_main, ConstraintSet.START, 0);
//R.id.id_tv_3右边与父布局右边对齐
applyConstraintSet.connect(R.id.id_tv_2, ConstraintSet.END, R.id.id_main, ConstraintSet.END, 0);
//R.id.id_tv_1的右边与R.id.id_tv_2的左侧对齐
applyConstraintSet.connect(R.id.id_tv_1, ConstraintSet.END, R.id.id_tv_2, ConstraintSet.START, 0);
applyConstraintSet.connect(R.id.id_tv_2, ConstraintSet.START, R.id.id_tv_1, ConstraintSet.END, 0);
//R.id.id_tv_2的右边与R.id.id_tv_3的左侧对齐
applyConstraintSet.connect(R.id.id_tv_2, ConstraintSet.END, R.id.id_tv_3, ConstraintSet.START,0);
applyConstraintSet.connect(R.id.id_tv_3, ConstraintSet.START, R.id.id_tv_2, ConstraintSet.END,0);
applyConstraintSet.connect(R.id.id_tv_3, ConstraintSet.END, R.id.id_main, ConstraintSet.END,0);
//设置ChainStyle
applyConstraintSet.setHorizontalChainStyle(R.id.id_tv_1, ConstraintSet.CHAIN_PACKED);
applyConstraintSet.constrainWidth(R.id.id_tv_1, ConstraintSet.WRAP_CONTENT);
applyConstraintSet.constrainHeight(R.id.id_tv_2, ConstraintSet.WRAP_CONTENT);
applyConstraintSet.constrainWidth(R.id.id_tv_2, ConstraintSet.WRAP_CONTENT);
applyConstraintSet.constrainHeight(R.id.id_tv_2, ConstraintSet.WRAP_CONTENT);
applyConstraintSet.constrainWidth(R.id.id_tv_3, ConstraintSet.WRAP_CONTENT);
applyConstraintSet.constrainWidth(R.id.id_tv_3, ConstraintSet.WRAP_CONTENT);
applyConstraintSet.applyTo(constraintLayout);
}
要实现三种不同的排列,只需要改变ChainStyle即可
//设置ChainStyle
applyConstraintSet.setHorizontalChainStyle(R.id.id_tv_1, ConstraintSet.CHAIN_PACKED);
applyConstraintSet.setHorizontalChainStyle(R.id.id_tv_1, ConstraintSet.CHAIN_SPREAD_INSIDE);
applyConstraintSet.setHorizontalChainStyle(R.id.id_tv_1, ConstraintSet.CHAIN_SPREAD);
如同最开始的gif动画,其实就是layout1切换到layout2,前提是layout1中view与layout2view id必须对应,多一个或者少一个都会报Exception:
首先我们准备两个Layout:
R.layout.activity_constraint_layout
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/id_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/id_image"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_margin="20dp"
android:scaleType="fitStart"
android:src="@drawable/about_bg"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/id_tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/str_title"
app:layout_constraintLeft_toRightOf="@+id/id_image"
app:layout_constraintTop_toTopOf="@+id/id_image" />
<TextView
android:id="@+id/id_tv_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginStart="12dp"
android:maxLines="3"
android:text="@string/str_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toRightOf="@+id/id_image"
app:layout_constraintTop_toBottomOf="@+id/id_tv_title" />
<Button
android:id="@+id/id_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:onClick="apply"
android:text="apply"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<Button
android:id="@+id/id_btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="reset"
android:text="reset"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/id_btn" />
android.support.constraint.ConstraintLayout>
R.layout.activity_constraint_layout2
<android.support.constraint.ConstraintLayout 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">
<ImageView
android:id="@+id/id_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:scaleType="fitStart"
android:src="@drawable/about_bg"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/id_tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:text="@string/str_title"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/id_image" />
<TextView
android:id="@+id/id_tv_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="6dp"
android:text="@string/str_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/id_tv_title" />
<Button
android:id="@+id/id_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:onClick="apply"
android:text="apply"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<Button
android:id="@+id/id_btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="reset"
android:text="reset"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/id_btn" />
android.support.constraint.ConstraintLayout>
两个XML解析图为:
然后切换一下就可以了:
public class ConstraintLayoutActivity extends AppCompatActivity {
private ConstraintLayout constraintLayout ;
private ConstraintSet applyConstraintSet = new ConstraintSet();
private ConstraintSet resetConstraintSet = new ConstraintSet();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_constraint_layout);
constraintLayout = findViewById(R.id.id_main);
applyConstraintSet.clone(constraintLayout);
resetConstraintSet.clone(this,R.layout.activity_constraint_layout2);
}
public void apply(View view) {
TransitionManager.beginDelayedTransition(constraintLayout);
resetConstraintSet.applyTo(constraintLayout);
}
public void reset(View view) {
TransitionManager.beginDelayedTransition(constraintLayout);
applyConstraintSet.applyTo(constraintLayout);
}
}
参考:
1.http://www.uwanttolearn.com/android/constraint-layout-animations-dynamic-constraints-ui-java-hell/
2.https://github.com/OCNYang/Android-Animation-Set/tree/master/constraint-animation