1、简介
我在我的博客Android–LayoutAnimation介绍中介绍了布局动画,所谓布局动画就是对 ViewGroup 这样的容器去做动画,而不是像补间动画这样只处理某一个View对象。
那篇博客中我着重讲了 LayoutAnimationController 这个类,它是用来指定一个应用到 ViewGroup 的每个子View的动画。
这里我要讲讲 LayoutTransition 这个类,在Android应用开发的时候经常会用到View的setVisibility()方法来动态隐藏和显示view,但是这样子是没有过渡动画的,变化的时候会显得很生硬。
而 LayoutTranstion 类用于当前布局容器中有View添加,删除,隐藏,显示的时候定义布局容器自身的动画和View的动画。也就是说当一个LinerLayout中隐藏一个view的时候,我们可以自定义整个LinerLayout容器因为隐藏了view而改变的动画,同时还可以自定义被隐藏的view自己消失时候的动画。你可以先实例化一个LayoutTransition对象,通过setLayoutTransition()方法将对象设置进一个布局容器ViewGroup中去。
private LinearLayout container;
private LayoutTransition mTransitioner;
.
.
.
mTransitioner = new LayoutTransition();
container.setLayoutTransition(mTransitioner);
此外还有一个更简单地使用方法,在xml文件中我们在容器的中下面一句代码:
android:animateLayoutChanges="true"
这样,每当有子view从容器中出现或消失的时候,默认的animator就会被自动调用。当然,我们也可以通过setAnimator()来设置自定义的动画。
2、LayoutTransition
LayoutTransition类定义了如下几种布局容器动画类型:
- APPEARING :当view出现或者添加的时候,view出现的动画
- DISAPPEARING :当view消失或者隐藏的时候,view消失的动画
- CHANGE_APPEARING :当添加view导致布局容器改变的时候,整个布局容器的动画
- CHANGE_DISAPPEARING :当删除或者隐藏view导致布局容器改变的时候,整个布局容器的动画
- CHANGE:当不是由于View出现或消失造成对其他View位置改变的时候整个布局容器的动画
3、LayoutTransition使用
这里我写个例子介绍一下 LayoutTranstion 在代码中的具体使用,演示 LayoutTransition 各种动画框架的效果。
1、基本使用
public class LayoutTransitionActivity extends AppCompatActivity {
private ViewGroup viewGroup;
private GridLayout mGridLayout;
private LayoutTransition mTransition;
private int count = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout_transition);
viewGroup = (ViewGroup) findViewById(R.id.container);
mGridLayout = new GridLayout(this);
mGridLayout.setColumnCount(5);
viewGroup.addView(mGridLayout);
// 默认动画全部开启
mTransition = new LayoutTransition();
mGridLayout.setLayoutTransition(mTransition);
}
public void addView(final View view) {
final Button button = new Button(this);
button.setText(++count + "");
Resources r = this.getResources();
int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, r.getDisplayMetrics());
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.width = px;
button.setLayoutParams(params);
mGridLayout.addView(button, Math.min(1, mGridLayout.getChildCount()));
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mGridLayout.removeView(button);
}
});
}
}
如果不用setAnimator()方法重新设置 LayoutTransition 的动画,这里就默认所有动画框架都启用。因为要让大家更直观的看到添加View的动画,所以把新加进来的 Button 在GridLayout中的索引更改为1,这样就很清晰的看到其它 View 的变化。
2、修改动画
接下来我再动态的改变 LayoutTransition 的动画框架的启用,让大家与不用 LayoutTransition 是对比,也加深大家对那四种动画的理解。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.ht.animator.LayoutTransitionActivity">
<Button
android:onClick="addView"
android:text="add"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:id="@+id/button" />
<CheckBox
android:id="@+id/id_appear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="APPEARING" />
<CheckBox
android:id="@+id/id_change_appear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="CHANGE_APPEARING" />
<CheckBox
android:id="@+id/id_disappear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="DISAPPEARING" />
<CheckBox
android:id="@+id/id_change_disappear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="CHANGE_DISAPPEARING " />
</LinearLayout>
我再布局文件中添加了四个 CheckBox,用来四种动画框架的启用,然后就要在Java代码里为这四个控件初始化,设置监听事件,接口的引用就不提啦。
private CheckBox mAppear, mChangeAppear, mDisAppear, mChangeDisAppear;
mAppear = (CheckBox) findViewById(R.id.id_appear);
mChangeAppear = (CheckBox) findViewById(R.id.id_change_appear);
mDisAppear = (CheckBox) findViewById(R.id.id_disappear);
mChangeDisAppear = (CheckBox) findViewById(R.id.id_change_disappear);
mAppear.setOnCheckedChangeListener(this);
mChangeAppear.setOnCheckedChangeListener(this);
mDisAppear.setOnCheckedChangeListener(this);
mChangeDisAppear.setOnCheckedChangeListener(this);
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mTransition = new LayoutTransition();
mTransition.setAnimator(
LayoutTransition.APPEARING,
(mAppear.isChecked() ? mTransition
.getAnimator(LayoutTransition.APPEARING) : null));
mTransition
.setAnimator(
LayoutTransition.CHANGE_APPEARING,
(mChangeAppear.isChecked() ? mTransition
.getAnimator(LayoutTransition.CHANGE_APPEARING)
: null));
mTransition.setAnimator(
LayoutTransition.DISAPPEARING,
(mDisAppear.isChecked() ? mTransition
.getAnimator(LayoutTransition.DISAPPEARING) : null));
mTransition.setAnimator(
LayoutTransition.CHANGE_DISAPPEARING,
(mChangeDisAppear.isChecked() ? mTransition
.getAnimator(LayoutTransition.CHANGE_DISAPPEARING)
: null));
mGridLayout.setLayoutTransition(mTransition);
}
这里用了 LayoutTransition 的两个方法:
void setAnimator(int transitionType, Animator animator)
Animator getAnimator(int transitionType)
setAnimator 显然是更改对应类型的动画啦,这里如果是选中状态,则保持对应动画类型的默认动画,否则就设置为空,效果就是与没设置 LayoutTransition 一样啦,当然只是设置为空的那一个动画类型而已。
可以很清楚的看到,当取消 APPEARING 的选中,则添加的 Button 不会出现淡入的动画,而其它Button是不受影响的。其它选择框也是如此的效果。
3、自定义动画
既然可以把动画设置为空,当然也可以自定义动画啦,设置时间等ValueAnimator 和 ObjectAnimator的方法也可以实现。
mTransition.setAnimator(LayoutTransition.APPEARING, (mAppear
.isChecked() ? ObjectAnimator.ofFloat(this, "scaleX", 0, 1)
: null));
这里就用我们的放大效果的动画替换了系统默认的LayoutTransition.APPEARING。
结束语:本文仅用来学习记录,参考查阅。