Android属性动画Property Animation系列三之LayoutTransition(布局容器动画)

在上一篇中我们学习了属性动画的ObjectAnimator使用,不了解的可以看看 Android属性动画Property Animation系列一之ObjectAnimator。这一篇我们来学点新的东西。做项目的时候应该碰到这种问题:根据不同条件显示或者隐藏一个控件或者布局,我们能想到的第一个方法就是 调用View.setVisibility()方法。虽然实现了显示隐藏效果,但是总感觉这样的显示隐藏过程很僵硬,让人不是很舒服,那么有没有办法能让这种显示隐藏有个过渡的动画效果呢?答案是肯定的,不言而喻就是LayoutTransition类了。

上效果图

实现上面的效果只需要在布局容器中添加android:animateLayoutChanges=”true”属性就ok了。不信你看

布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="buttonClick"
            android:text="添加控件" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="buttonClick1"
            android:text="移除控件" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/parent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:animateLayoutChanges="true"
        android:orientation="vertical"></LinearLayout>

</LinearLayout>

如果布局容器中为添加android:animateLayoutChanges=”true”默认是么有动画效果的。该属性只能用在ViewGroup控件里,表示容器里面布局改变时有默认的动画效果,比如说添加控件,删除控件的时候就是默认的动画效果。

以上动画调用代码如下:

package com.xjp.animations;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;

/**
 * Description:
 * User: xjp
 * Date: 2015/5/22
 * Time: 15:06
 */

public class LayoutAnimationActivity extends Activity {

    private LinearLayout parent;
    private int i = 0;
    private int j = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_layout_animation);

        parent = (LinearLayout) findViewById(R.id.parent);
    }

    public void buttonClick(View view) {
        addButtonView();
    }

    public void buttonClick1(View view) {
        removeButtonView();
    }

    private void addButtonView() {
        i++;
        Button button = new Button(this);
        button.setText("button" + i);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        parent.addView(button, params);
    }

    private void removeButtonView() {
        if (i > 0)
            parent.removeViewAt(0);
    }
}

是不是发现很简单?除了布局中添加了android:animateLayoutChanges=”true”属性,代码中根本不需要做任何处理就有很舒服的过渡动画效果了。主要是添加了该属性之后在容器中有布局改变时系统会默认给该容器添加一个默认的动画效果。如果你觉得上面的的效果已经很nice~了,那你就太容易满足了,我们除了使用系统默认的布局容器动画,还可以自定义布局容器动画。现在该LayoutTransition类上场了。

LayoutTransition

该类用于当前布局容器中有View添加,删除,隐藏,显示的时候定义布局容器自身的动画和View的动画。也就是说当一个LinerLayout中隐藏一个view的时候,我们可以自定义 整个LinerLayout容器因为隐藏了view而改变的动画,同时还可以自定义被隐藏的view自己消失时候的动画。你可以先new一个LayoutTransition对象,通过setLayoutTransition()方法将对象设置进一个布局容器ViewGroup中去。代码如下:

    private LinearLayout container;
    private LayoutTransition mTransitioner;
 /**
     * 初始化容器动画
     */
    private void initTransition() {
        mTransitioner = new LayoutTransition();
        container.setLayoutTransition(mTransitioner);
    }

LayoutTransition类定义了如下几种布局容器动画类型。

  • APPEARING :当view出现或者添加的时候,view出现的动画
  • DISAPPEARING :当view消失或者隐藏的时候,view消失的动画
  • CHANGE_APPEARING :当添加view导致布局容器改变的时候,整个布局容器的动画
  • CHANGE_DISAPPEARING :当删除或者隐藏view导致布局容器改变的时候,整个布局容器的动画

你可以自定义这些动画,通过setAnimator() 方法把它们设置进一个 LayoutTransition 对象中去。

LayoutTransition的用法

APPEARING–view出现的动画

/**
         * view出现时 view自身的动画效果
         */
        ObjectAnimator animator1 = ObjectAnimator.ofFloat(null, "rotationY", 0F, 90F, 0F);
        mTransitioner.setAnimator(LayoutTransition.APPEARING, animator1);

定义一个旋转的属性动画,这里将动画对象置空,因为系统内部会将添加的view设置为动画对象。然后调用setAnimator()方法将动画设置进LayoutTransition对象mTransitioner中。

完整动画代码如下,具体解释都有注解

package com.xjp.animations;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.Keyframe;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;

/**
 * Description:布局动画Demo
 * User: xjp
 * Date: 2015/5/22
 * Time: 15:06
 */

public class LayoutAnimationActivity extends Activity {

    private int i = 0;
    private LinearLayout container;
    private LayoutTransition mTransitioner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_layout_animation);

        container = (LinearLayout) findViewById(R.id.parent);

        initTransition();
        setTransition();
    }

    /**
     * 初始化容器动画
     */
    private void initTransition() {
        mTransitioner = new LayoutTransition();
        container.setLayoutTransition(mTransitioner);
    }

    private void setTransition() {
        /**
         * view出现时 view自身的动画效果
         */
        ObjectAnimator animator1 = ObjectAnimator.ofFloat(null, "rotationY", 90F, 0F).
                setDuration(mTransitioner.getDuration(LayoutTransition.APPEARING));
        mTransitioner.setAnimator(LayoutTransition.APPEARING, animator1);

        /**
         * view 消失时,view自身的动画效果
         */
        ObjectAnimator animator2 = ObjectAnimator.ofFloat(null, "rotationX", 0F, 90F, 0F).
                setDuration(mTransitioner.getDuration(LayoutTransition.DISAPPEARING));
        mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, animator2);

        /**
         * view 动画改变时,布局中的每个子view动画的时间间隔
         */
        mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 30);
        mTransitioner.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 30);

        /**
         * 为什么这里要这么写?具体我也不清楚,ViewGroup源码里面是这么写的,我只是模仿而已
         * 不这么写貌似就没有动画效果了,所以你懂的!
         */
        PropertyValuesHolder pvhLeft =
                PropertyValuesHolder.ofInt("left", 0, 1);
        PropertyValuesHolder pvhTop =
                PropertyValuesHolder.ofInt("top", 0, 1);
        PropertyValuesHolder pvhRight =
                PropertyValuesHolder.ofInt("right", 0, 1);
        PropertyValuesHolder pvhBottom =
                PropertyValuesHolder.ofInt("bottom", 0, 1);

        /**
         * view出现时,导致整个布局改变的动画
         */
        PropertyValuesHolder animator3 = PropertyValuesHolder.ofFloat("scaleX", 1F, 2F, 1F);
        final ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder(
                this, pvhLeft, pvhTop, pvhRight, pvhBottom, animator3).
                setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_APPEARING));
        changeIn.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                View view = (View) ((ObjectAnimator) animation).getTarget();
                view.setScaleX(1.0f);
            }
        });
        mTransitioner.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);

        /**
         * view消失,导致整个布局改变时的动画
         */
        Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
        Keyframe kf1 = Keyframe.ofFloat(.5f, 2f);
        Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
        PropertyValuesHolder pvhRotation =
                PropertyValuesHolder.ofKeyframe("scaleX", kf0, kf1, kf2);
        final ObjectAnimator changeOut = ObjectAnimator.ofPropertyValuesHolder(
                this, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhRotation).
                setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_DISAPPEARING));
        changeOut.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                View view = (View) ((ObjectAnimator) animation).getTarget();
                view.setScaleX(1.0f);
            }
        });
        mTransitioner.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeOut);
    }

    public void buttonClick(View view) {
        addButtonView();
    }

    public void buttonClick1(View view) {
        removeButtonView();
    }

    private void addButtonView() {
        i++;
        Button button = new Button(this);
        button.setText("button" + i);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        container.addView(button, Math.min(1, container.getChildCount()), params);
    }

    private void removeButtonView() {
        if (i > 0)
            container.removeViewAt(0);
    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="buttonClick"
            android:text="添加控件" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="buttonClick1"
            android:text="移除控件" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/parent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:animateLayoutChanges="true"
        android:orientation="vertical"></LinearLayout>

</LinearLayout>

最后来一张效果图:

布局动画之layoutAnimation

很多时候我们想要在第一次加载ListView或者GridView的时候能有个动画效果来达到一个很好的过度效果。比如下面的效果

实现这种效果只需要在布局中添加android:layoutAnimation=”@anim/layout”属性就好了。接下来我们来看看layout.xml动画怎么实现的?在res/anim目录下新建layout.xml文件,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/left"
    android:animationOrder="normal"
    android:delay="30%"></layoutAnimation>

android:delay 子类动画时间间隔 (延迟) 70% 也可以是一个浮点数 如“1.2”等

android:animationOrder=”random” 子类的显示方式 random表示随机

android:animationOrder 的取值有

normal 0 默认

reverse 1 倒序

random 2 随机

android:animation=”@anim/left” 表示孩子显示时的具体动画是什么代

在res/anim目录下新建left.xml文件,码如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="500"
        android:fromXDelta="100%"
        android:fromYDelta="0"
        android:toXDelta="0"
        android:toYDelta="0" />
    <alpha
        android:duration="500"
        android:fromAlpha="0"
        android:toAlpha="1" />
</set>

这样就实现了如上ListView的动画效果了。

当然我们也可以在代码中实现这种动画效果

private void initAinm() {
        //通过加载XML动画设置文件来创建一个Animation对象;
        Animation animation = AnimationUtils.loadAnimation(this, R.anim.left);
        //得到一个LayoutAnimationController对象;
        LayoutAnimationController lac = new LayoutAnimationController(animation);
        //设置控件显示的顺序;
        lac.setOrder(LayoutAnimationController.ORDER_REVERSE);
        //设置控件显示间隔时间;
        lac.setDelay(1);
        //为ListView设置LayoutAnimationController属性;
        listView.setLayoutAnimation(lac);
    }

通过AnimationUtils.loadAnimation加载item的动画来获得一个Animation对象,然后将Animation对象设置到LayoutAnimationController中来获得LayoutAnimationController对象,配置LayoutAnimationController对象的一些属性。最后将LayoutAnimationController对象设置到ListView中。

注意

layoutAnimation动画不仅仅限于ListView,GridView中,也可用于一切ViewGroup中。具体怎么用就看项目需求了。

总结

Android属性动画至此就基本介绍完毕了。其中基本的动画使用和实例也贴出来了,基本能满足日常开发需求,当然有更炫的动画时可以根据这些基础去实现。这么说,以后都可以不用补间动画了?貌似属性动画更加合理,因为这种动画改变的是属性而不仅仅是位置。

时间: 2024-10-25 10:35:32

Android属性动画Property Animation系列三之LayoutTransition(布局容器动画)的相关文章

Android属性动画Property Animation系列一之ObjectAnimator

转载请注明出处 http://blog.csdn.net/feiduclear_up/article/details/45915377 前面一篇博客解读了Android属性动画Property Animation系列一之ValueAnimator的相关知识点以及怎么使用.这篇博客继续解读Android 属性动画 ObjectAnimator 类的使用. ObjectAnimator 相比ValueAnimator类,ObjectAnimator更加实用,因为它真正可以作用在一个对象上.不过Obj

Android属性动画Property Animation系列一之ValueAnimator

Android动画分类 市面上的很多APP都用到动画效果,动画效果用的好可以提升用户的体验度.那么Android系统都有哪些机制的动画呢? 1.逐帧动画(frame-by-frame animation).逐帧动画的工作原理很简单,其实就是将一个完整的动画拆分成一张张单独的图片,然后再将它们连贯起来进行播放,类似于动画片的工作原理. 2.补间动画(tweened animation)则是可以对View进行一系列的动画操作,包括淡入淡出.缩放.平移.旋转四种. 3.属性动画Property Ani

Android 动画详解之属性动画(Property Animation)(下)

Hello,大家好,最近好长时间没有写博客了,因为我决定辞职了. 废话不多说,我们还是来看属性动画在上一篇Android 动画详解之属性动画(Property Animation)中我们简单的介绍了一下属性动画的用法,其实属性动画还有更多有趣的用法. 1,在xml中使用 在eclipse中我们右键新建xml可以选择新建属性动画,如图 我们选择objectAnimator,然后我们就会看到熟悉的一幕 然后我们用智能提示就可以看到更熟悉的 没错,这下我们应该知道怎么用xml布局来写属性动画了吧 <s

属性动画-Property Animation之ViewPropertyAnimator 你应该知道的一切

转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/52381558 出自[zejian的博客] 关联文章: 走进绚烂多彩的属性动画-Property Animation(上篇) 走进绚烂多彩的属性动画-Property Animation之Interpolator和TypeEvaluator(下篇) ??原本打算这篇作为属性动画的完结篇,但目前情况来看,估计无法完结,前两天研究了一下ViewPropertyAnimat

使用属性动画 &mdash; Property Animation

属性动画,就是通过控制对象中的属性值产生的动画.属性动画是目前最高级的2D动画系统. 在API Level 11中添加.Property Animation号称能控制一切对象的动画,包括可见的和不可见的. 但是,日常开发中我们一般都是对UI定制动画.   使用ObjectAnimator ObjectAnimator是其中比较容易使用的一个动画类,它继承自ValueAnimator, 说比较容易使用是因为它在动画启动后自动监视属性值的变化并把值赋给对象属性, 而ValueAnimator则只监视

Android 属性系统 Property service 设定分析 (转载)

转自:http://blog.csdn.net/andyhuabing/article/details/7381879 Android 属性系统 Property service 设定分析 在Window中有个注册表的东东,可以存储一些类似key:value的 键值对,而在android平台上也有类似的机制叫做属性服务(Property service)进行初始化,设置及修改和查询的功能,adb shell命令使用 setprop 及 getprop 可以看到. 问题: SurfaceFling

Android学习之 属性动画&lt;Property Animation&gt;

property 动画系统是相当健壮的框架,它几乎可以动画显示任何对象. 你可以定义一个动画来定时改变任何对象的属性值,不论该对象是否在屏幕上显示. property 动画将以一定的时间间隔修改属性值(对象中的字段值). 要实现动画显示,你须指定对象的相应属性(比如对象的屏幕位置),以及动画时长.动画时间间隔. property 动画系统能让你设定以下动画要素: 1.持续时间:指定动画的持续显示时间.默认的时长是300毫秒. 2.插值因子:指定属性值的变化方式,表示为关于动画已显示时间的函数.

Android进阶——属性动画Property Animation详解(一)

引言 前一篇文章Android入门--补间动画和帧动画应用小结总结了补间动画和帧动画及一些相关类的应用,基本可以掌握简单的缩放.旋转.透明度变化.平移的动画效果,但是需要实现更复杂的动画效果时,比如说希望View的切换动画.Layout的切换动画.3D旋转动画等等,这些View Animation都无法做到.此时Property Animation应运而生,这篇主要总结下属性动画的相关知识点. 一.Property Animation属性动画概述 属性动画,在我最先接触到Android 1.5时

Android动画--属性动画Property Animation

简介 属性动画包含: ObjectAnimator 动画的执行类 ValueAnimator 动画的执行类 AnimatorSet 用于控制一组动画的执行:线性,一起,每个动画的先后执行等. AnimatorInflater 用户加载属性动画的xml文件 ObjectAnimator 单一属性动画 缩放X轴:ScaleX ObjectAnimator().ofFloat(imageView,"ScaleY",1.0f,0.0f).setDuration(3000).start(); 缩