属性动画 LayoutTransition AnimatorInflater Keyframe 新特性

LayoutTransition设置动画



使用LayoutTransition可为布局的容器设置动画,当容器中的视图层次发生变化时产生相应的过渡的动画效果
过渡的类型一共有四种:
  • LayoutTransition.APPEARING 当一个View在ViewGroup中出现时,对此View设置的动画
  • LayoutTransition.CHANGE_APPEARING 当一个View在ViewGroup中出现时,对此View对其他View位置造成影响,对其他View设置的动画
  • LayoutTransition.DISAPPEARING  当一个View在ViewGroup中消失时,对此View设置的动画
  • LayoutTransition.CHANGE_DISAPPEARING 当一个View在ViewGroup中消失时,对此View对其他View位置造成影响,对其他View设置的动画
AnimateLayoutChanges动画:         ViewGroup的xml属性中有一个animateLayoutChanges属性,设置该属性为true,可以添加ViewGroup增加view的过渡效果: 示例:         mTransition = new LayoutTransition();         mTransition.setAnimator(LayoutTransition.APPEARING, ObjectAnimator.ofFloat(this, "scaleX", 0, 1));         mTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, mTransition.getAnimator(LayoutTransition.CHANGE_APPEARING));         mTransition.setAnimator(LayoutTransition.DISAPPEARING, mTransition.getAnimator(LayoutTransition.DISAPPEARING));         mTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, mTransition.getAnimator(LayoutTransition.CHANGE_DISAPPEARING));         gl_container.setLayoutTransition(mTransition);  

XML中设置属性动画



set标签的orderring属性设置为together表示同时播放,sequentially表示一个接一个播放

缩放、反转等都有中心点或者轴,默认为中心缩放,中间对称线为反转线,通过setPivotX(),setPivotY()可改变中心的位置

        Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scale);

        mChangeAppear.setPivotX(0);//设置缩放、反转时的中心点或者轴

        mChangeAppear.setPivotY(0);

        mChangeAppear.invalidate();//设置后要显示的调用invalidate

        anim.setTarget(mChangeAppear);

        anim.start();  

KeyFrame动画



KeyFrame是一个【时间/值】对,通过它可以定义一个在特定时间的特定状态,即【关键帧】,而且在两个keyFrame之间可以定义不同的【Interpolator】,就好像多个动画的拼接,第一个动画的结束点是第二个动画的开始点。

KeyFrame是抽象类,要通过ofInt(),ofFloat(),ofObject()获得适当的KeyFrame,然后通过PropertyValuesHolder.ofKeyframe获得PropertyValuesHolder对象,然后通过ObjectAnimator.ofPropertyValuesHolder获得一个Animator对象。
      Keyframe kf0 = Keyframe.ofInt(0, 300);

        Keyframe kf1 = Keyframe.ofInt(0.2f, 800);//动画开始1/5时 Width=600

        Keyframe kf2 = Keyframe.ofInt(0.4f, 300);

        PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2);

        ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(mDisAppear, pvhRotation);

        rotationAnim.setDuration(5000).start();

View的animate动画-新API



在SDK11的时候,给View添加了animate方法,可以使用一行代码非常方便的实现动画效果。

此后在SDK12,SDK16又分别添加了withStartAction和withEndAction用于在动画前、动画后执行一些操作,当然也可以.setListener(listener)完成此操作。

如:

view.animate().alpha(0.2F).y(1000).setDuration(2000).withStartAction(new Runnable() {

            @Override

            public void run() {

                mChangeDisAppear.setX(200);

            }

        }).withEndAction(new Runnable() {

            @Override

            public void run() {

                mChangeDisAppear.setRotation(-30);//是相对初始值转了-30°

            }

        }).start();

我们也可以使用PropertyValueHolder实现上面的变化,效果与上面一样         PropertyValuesHolder pvhA = PropertyValuesHolder.ofFloat("alpha", 1f, 0f);         PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 0, 200);         ObjectAnimator.ofPropertyValuesHolder(iv, pvhA, pvhY).setDuration(1000).start(); 注意,这种动画不再是View动画了,而是属性动画的一种,因为改变了控件的实际属性。

代码


public class MainActivity extends Activity implements OnCheckedChangeListener {

    private GridLayout gl_container;//放置按钮的父布局

    private int mVal;//按钮的编号

    private LayoutTransition mTransition;//布局动画,当容器中的视图发生变化时存在过渡的动画效果

    private CheckBox mAppear, mChangeAppear, mDisAppear, mChangeDisAppear;

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        gl_container = (GridLayout) findViewById(R.id.gl_container);

        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);

        //CheckBox选中状态改变监听,默认全部选中,即动画全部开启

        mAppear.setOnCheckedChangeListener(this);

        mChangeAppear.setOnCheckedChangeListener(this);

        mDisAppear.setOnCheckedChangeListener(this);

        mChangeDisAppear.setOnCheckedChangeListener(this);

        mTransition = new LayoutTransition();

        gl_container.setLayoutTransition(mTransition);

    }

    @Override

    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

        mTransition = new LayoutTransition();

        //当一个View在ViewGroup中【出现】时,对此【View】设置的动画

        mTransition.setAnimator(LayoutTransition.APPEARING, //=2,下面使用的是自定义的动画

                (mAppear.isChecked() ? ObjectAnimator.ofFloat(this, "scaleX", 0, 1) : null));

        //当一个View在ViewGroup中【出现】时,对此View对其他View位置造成影响,对【其他View】设置的动画

        mTransition.setAnimator(LayoutTransition.CHANGE_APPEARING,//=0,下面都是使用默认的动画

                (mChangeAppear.isChecked() ? mTransition.getAnimator(LayoutTransition.CHANGE_APPEARING) : null));

        //当一个View在ViewGroup中【消失】时,对此【View】设置的动画

        mTransition.setAnimator(LayoutTransition.DISAPPEARING, //=3

                (mDisAppear.isChecked() ? mTransition.getAnimator(LayoutTransition.DISAPPEARING) : null));

        //当一个View在ViewGroup中【消失】时,对此View对其他View位置造成影响,对【其他View】设置的动画

        mTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,//=1

                (mChangeDisAppear.isChecked() ? mTransition.getAnimator(LayoutTransition.CHANGE_DISAPPEARING) : null));

        gl_container.setLayoutTransition(mTransition);

    }

    // 向GridLayout中添加按钮

    public void addBtn(View view) {

        final Button button = new Button(this);

        button.setText("" + (++mVal));

        gl_container.addView(button, gl_container.getChildCount());//放置在最后那个位置

        button.setOnClickListener(new OnClickListener() {

            @Override

            public void onClick(View v) {

                gl_container.removeView(button);

            }

        });

    }

    //XML属性动画1,单个动画     public void xmlAnim1(View view) {         // 加载动画         Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scalex);         mAppear.setPivotX(0);//设置缩放、反转时的中心点或者轴         mAppear.invalidate();//设置后要显示的调用invalidate才能生效         anim.setTarget(mAppear);         anim.start();     }     //XML属性动画2,多动画     public void xmlAnim2(View view) {         Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scale);         mChangeAppear.setPivotX(0);//设置缩放、反转时的中心点或者轴         mChangeAppear.setPivotY(0);         mChangeAppear.invalidate();//设置后要显示的调用invalidate         anim.setTarget(mChangeAppear);         anim.start();     }
    //Keyframe动画     public void keyframe(View view) {         Keyframe kf0 = Keyframe.ofInt(0, 300);         Keyframe kf1 = Keyframe.ofInt(0.2f, 800);//动画开始1/5时 Width=600         Keyframe kf2 = Keyframe.ofInt(0.4f, 300);         Keyframe kf3 = Keyframe.ofInt(0.6f, 100);         Keyframe kf4 = Keyframe.ofInt(0.8f, 50);         Keyframe kf5 = Keyframe.ofInt(1f, 500);         PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf3, kf4, kf5);         ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(mDisAppear, pvhRotation);         rotationAnim.setDuration(5000).start();     }
    //新版本View动画     public void viewAnimForNew(View view) {         mChangeDisAppear.animate().alpha(0.2F).y(1000).setDuration(2000).withStartAction(new Runnable() {             @Override             public void run() {                 mChangeDisAppear.setX(200);                 mChangeDisAppear.setRotation(180);             }         }).withEndAction(new Runnable() {             @Override             public void run() {                 mChangeDisAppear.setX(200);                 mChangeDisAppear.setY(300);                 mChangeDisAppear.setAlpha(1.0f);                 mChangeDisAppear.setRotation(-30);//是相对初始值转了-30°             }         }).start();     } }

XML动画



scalex.xml
<?xml version="1.0" encoding="utf-8"?>

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"

    android:duration="500"

    android:interpolator="@android:anim/accelerate_interpolator"

    android:propertyName="scaleX"

    android:repeatCount="1"

    android:repeatMode="reverse"

    android:startOffset="1000"

    android:valueFrom="2.5"

    android:valueTo="10"

    android:valueType="floatType" >

</objectAnimator>

scale.xml <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"     android:ordering="sequentially" >     <objectAnimator         android:duration="500"         android:propertyName="rotationX"         android:startOffset="0"         android:valueFrom="0"         android:valueTo="360" >     </objectAnimator>     <objectAnimator         android:duration="200"         android:propertyName="scaleY"         android:startOffset="500"         android:valueFrom="1"         android:valueTo="1.7" >     </objectAnimator>     <objectAnimator         android:duration="200"         android:propertyName="scaleX"         android:startOffset="700"         android:valueFrom="1"         android:valueTo="1.5" >         <objectAnimator             android:duration="100"             android:propertyName="alpha"             android:startOffset="900"             android:valueFrom="1"             android:valueTo="0.2" >         </objectAnimator>     </objectAnimator> </set>

布局



  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:id="@+id/id_container"

    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="0dp"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:onClick="xmlAnim1"

            android:text="XML属性动画1" />

        <Button

            android:layout_width="0dp"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:onClick="xmlAnim2"

            android:text="XML属性动画2" />

    </LinearLayout>

    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:orientation="horizontal" >

        <Button

            android:layout_width="0dp"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:onClick="keyframe"

            android:text="Keyframe动画" />

        <Button

            android:layout_width="0dp"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:onClick="viewAnimForNew"

            android:text="view的animate动画" />

    </LinearLayout>

    <CheckBox

        android:id="@+id/id_appear"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:background="#200f"

        android:checked="true"

        android:text="APPEARING" />

    <CheckBox

        android:id="@+id/id_change_appear"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:background="#2ff0"

        android:checked="true"

        android:text="CHANGE_APPEARING" />

    <CheckBox

        android:id="@+id/id_disappear"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:background="#20f0"

        android:checked="true"

        android:text="DISAPPEARING" />

    <CheckBox

        android:id="@+id/id_change_disappear"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:background="#2f00"

        android:checked="true"

        android:text="CHANGE_DISAPPEARING " />

    <Button

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_marginBottom="10dp"

        android:onClick="addBtn"

        android:text="点击添加按钮,点击添加的按钮删除按钮" />

    <GridLayout

        android:id="@+id/gl_container"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_gravity="center_horizontal"

        android:animateLayoutChanges="false"

        android:background="#40f0"

        android:columnCount="5" />

</LinearLayout>

来自为知笔记(Wiz)

附件列表

时间: 2024-10-24 15:19:59

属性动画 LayoutTransition AnimatorInflater Keyframe 新特性的相关文章

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

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

接口、接口优点、接口的属性和方法特性、接口与继承的区别、接口与抽象类的区别、匿名实现类、JDK1.8新特性、打印类名称

接口里的属性,必须是公共的/默认的&静态的&Final&初始化后的属性: 接口里所有方法都是抽象的. 接口和继承---先天有的用继承,后天学习的用接口: 接口特性-------- 1.接口不可以被实例化: 2.实现类必须实现接口中所有方法,否则实现类必须是抽象类 3.实现类可以实现多个接口,来弥补Java不能多继承: 4.接口中的变量都是静态常量:(静态的-可以通过类的名字点-直接调用:) ----------------------------------------------

H5 新特性之全局属性一

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body> <!--<!DOCTYPE html>--><!--<html lang="en">--><!--<he

最新iOS 6 in Xcode4.5新特性——Storyboard和属性自动绑定

最新iOS 6 in Xcode4.5新特性编程之二(上)——Storyboard和属性自动绑定 从Xcode 4.3开始,Storyboard 就是iOS 5和iOS 6中令人兴奋的一个新特性,他将为你在创建用户界面上节省很多时间. 那么究竟什么是Storyboard呢?我将用一幅图片来向你展示: 下面这个就是本实例中即将用到的Storyboard. 关于故事板编程,我在“最新Xcode 4.3.2 下使用Storyboard和ARC开发iPhone4程序 03——Storyboard类及使用

css3的新特性选择器-------属性选择器

自己学css的时候比较乱,这次趁着复习把css3的新特性选择器和css2以前不怎么用的选择器做一个总结 <div id="parent"> <p>I'm a example</p> <p id="one">I'm a example</p> <p>I'm a example</p> <p>I'm a example</p> <p>I'm a exa

HTML5基础知识汇总_(2)自己定义属性及表单新特性

自己定义属性data-* 说起这个属性,事实上如今非经常见了;怎么说呢,由于在一些框架都能看到他的身影!!! 比方Jquery mobile,里面非常频繁的使用了这个属性; 这个属性是哪里来的-.当然是尾随最新的H5一起出来的-.. 兼容性在PC端仅仅能呢说一般般(眼下.比較老式浏览器居多),,手机端支持还是比較OK的; 虽说是自己定义属性,可是还是有一定的规格的,,比方前缀必须是data-[自己定义属性]; 比方 <div data-id="id"></div>

ios11的新特性——prefersLargeTitles属性

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #703daa; background-color: #ffffff } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #008400; background-color: #ffffff } p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; fo

手把手教你如何用java8新特性将List中按指定属性排序,过滤重复数据

在java中常常会遇到这样一个问题,在实际应用中,总会碰到对List排序并过滤重复的问题,如果List中放的只是简单的String类型过滤so easy,但是实际应用中并不会这么easy,往往List中放的是一个类,类中有多个属性,要过滤重复数据,而且这个重复数据要按自己指定的属性过滤,但是要想按照其它属性排序顺序过滤,所以要先排序一下,然后按照某个属性过滤. 实体类如下所示,大家只要创建下面的实体类,无需继承父类,大家不会注解式风格的话,请自行加上getter/setter方法. 首先看看gr

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

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