转载

Layout Animation

Defines the layout animation to use the first time the ViewGroup is laid out. Layout animations can also be started manually after the first layout.

layoutAnimation作用的对象是此ViewGroup的直接子view。很好用,比如可以定义ListView条目出现时的动画效果。如下实现的一个简单效果:

Layout Animation

layout_anim.xml:

<layoutAnimationxmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/left_in"
    android:animationOrder="reverse"
    android:delay="0.5"/>

解释:

android:delay=”0.5”: Fraction of the animation duration used to delay the beginning of the animation of each child.意思是一个子view动画执行了50%时,开始执行下一个view动画

android:animationOrder=”reverse”: 子view显示方式,正序、反序、随机

android:animation=”@anim/left_in”: 子view执行的动画

left_in.xml:

<setxmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="2000"
        android:fromXDelta="-100%p"
        android:interpolator="@android:anim/linear_interpolator"
        android:toXDelta="0" />
</set>

布局如下:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layoutAnimation="@anim/layout_anim"
    android:orientation="vertical">
    <Button
        android:id="@+id/bt_activity_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="activity_layout" />
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="@color/colorPrimary">
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="2" />
    </FrameLayout>
</LinearLayout>

java代码对应实现:

Animation animation = AnimationUtils.loadAnimation(this, R.anim.left_in);
LayoutAnimationController lac = new LayoutAnimationController(animation);
lac.setOrder(LayoutAnimationController.ORDER_REVERSE);
lac.setDelay(0.5f);
container.setLayoutAnimation(lac);

LayoutAnimationt效果只有在初次创建时才会有动画,再添加的子View将不再有动画效果,另外类似的还有gridLayoutAnimation

如果想修改动画的一些展现形式,可以继承LayoutAnimationController重写对应方法,如修改对应的子view显示顺序,则可以修改如下方法实现:

protectedintgetTransformedIndex(AnimationParameters params){
    switch (getOrder()) {
        case ORDER_REVERSE:
            return params.count - 1 - params.index;
        case ORDER_RANDOM:
            if (mRandomizer == null) {
                mRandomizer = new Random();
            }
            return (int) (params.count * mRandomizer.nextFloat());
        case ORDER_NORMAL:
        default:
            return params.index;
    }
}

LayoutTransition

当一个ViewGroup中的直接子View 有add/remove/visible/gone/invisible状态变化时,我们想给这些变化一个动画效果,这时就用到了LayoutTransition

android:animateLayoutchanges

系统提供了默认的布局转换动画,只需在ViewGroup的XML布局文件中把添加属性 android:animateLayoutchanges=”true”,默认的效果如下:

Layout Animation

自定义变换动画

自定义变换动画需要用到LayoutTransition类,此类提供了各种属性设置,然后再把此对象传递给ViewGroup,即可。

LayoutTransition四种动画类型:

  • APPEARING - 新的子view add或者visible时,此子view的出现效果
  • CHANGE_APPEARING - 新的子view add或者visible时,其它子view的动画效果
  • DISAPPEARING - 新的子view remove或者gone时,此子view的消失效果
  • CHANGE_DISAPPEARING -新的子view remove或者gone时,其它子view的消失效果

看下图实现的效果,实现了前3种动画效果:

Layout Animation

图片功能表现了view的 add/remove 和 invisible/visible 改变时的动画效果

布局文件activity_layout_transition:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/container">
 
    <Button
        android:id="@+id/add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add button" />
 
    <Button
        android:id="@+id/remove"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="remove button" />
 
    <Button
        android:id="@+id/change_state"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="First View Visible/Gone" />
</LinearLayout>

Activity主要代码:

@Override
protectedvoidonCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_layout_transition);
    findViewById(R.id.add).setOnClickListener(this);
    findViewById(R.id.remove).setOnClickListener(this);
    findViewById(R.id.change_state).setOnClickListener(this);
    mContainerView = (LinearLayout) findViewById(R.id.container);
 
    mTransition = new LayoutTransition();
 
    ObjectAnimator animatorAppear = ObjectAnimator.ofFloat(this, "translationX", -600, 0);
    ObjectAnimator animatorDissappear = ObjectAnimator.ofFloat(this, "translationX", 0, -600);
 
    // 动画:CHANGE_APPEARING
    PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 0);
    PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 0);
    PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofFloat("scaleX", 1f, 0.5f, 1f);
    PropertyValuesHolder pvhScaleY = PropertyValuesHolder.ofFloat("scaleY", 1f, 0.5f, 1f);
    ObjectAnimator animatorChangeAppear = ObjectAnimator.ofPropertyValuesHolder(this, pvhLeft, pvhTop, pvhScaleX, pvhScaleY);
 
    mTransition.setAnimator(LayoutTransition.APPEARING, animatorAppear);
    mTransition.setAnimator(LayoutTransition.DISAPPEARING, animatorDissappear);
    mTransition.setInterpolator(LayoutTransition.APPEARING, new AccelerateInterpolator());
    mTransition.setInterpolator(LayoutTransition.DISAPPEARING, new LinearInterpolator());
    mTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, animatorChangeAppear);
    mContainerView.setLayoutTransition(mTransition);
}
 
@Override
publicvoidonClick(View v){
    switch (v.getId()) {
        case R.id.add:
            addView();
            break;
        case R.id.remove:
            removeView();
            break;
        case R.id.change_state:
            chnageState();
            break;
    }
}
 
 
privatevoidchnageState(){
    if (mContainerView.getChildCount() > 3) {
        View view = mContainerView.getChildAt(0);
        view.setVisibility(view.getVisibility() == View.VISIBLE ? View.INVISIBLE : View.VISIBLE);
    }
}
 
privatevoidaddView(){
    mButtonValue++;
    Button button = new Button(this);
    button.setText("button" + mButtonValue);
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(600, ViewGroup.LayoutParams.WRAP_CONTENT);
    button.setLayoutParams(params);
    mContainerView.addView(button, 0);
}
 
privatevoidremoveView(){
    if (mContainerView.getChildCount() > 3) {
        mContainerView.removeViewAt(0);
    }
}

CHANGE_APPEARING/CHANGE_DISAPPEARING动画注意事项:

  1. 使用ObjectAnimator构造的动画无效,需要使用PropertyValuesHolder构造动画。
  2. left、top属性的变动是必写的。
  3. 属性动画的参数值,第一个值和最后一个值必须相同,不然此属性所对应的的动画将无效。

另外还有其它方便的api供调用,这里就不说了。

原文  http://blog.edreamoon.com/2016/12/17/Layout-Animation/
正文到此结束
Loading...