Android中编写属性动画PropertyAnimation的进阶实例
0、基础回顾
propertyanimation,属性动画,顾名思义就是利用对象的属性变化形成动画的效果。属性动画的类可以用animator这个抽象类来表示,通常使用它的子类:animatorset和valueanimator,同时valueanimator有两个子类分别是objectaniamtor和timeanimator。
定义属性动画的xml资源的时候通常可以是如下三个元素之一作为根元素:
<set>元素:该资源元素代表的是aniamtorset类,这个类可以包含<set>,<objectaniamtor>,<animator>三个子元素。
<objectanimator>元素:用于定义objectaniamtor类。
<animator>元素:用于定义valueanimator类。
比如说这里一个资源文件的定义如下:
<set android:ordering="[together|sequentially]"> <objectanimator android:propertyname="string" android:duration="int" android:valuefrom="float|int|color" android:valueto="float|int|color" android:startoffset="int" android:repeatcount="int" android:interpolator="" android:repeatmode="[reapeat|reverse]" android:valuetype="[inttype|floattype]"/> <animator android:duration="int" android:valuefrom="float|int|color" android:valueto="float|int|color" android:startoffset="int" android:repeatcount="int" android:interpolator="" android:repeatmode="[reapeat|reverse]" android:valuetype="[inttype|floattype]"/> <set> .... </set> </set>
属性文件通常保存在animator文件夹下面。
1、如何使用xml文件来创建属性动画
大家肯定都清楚,view animator 、drawable animator都可以在anim文件夹下创建动画,然后在程序中使用,甚至在theme中设置为属性值。当然了,属性动画其实也可以在文件中声明:
首先在res下建立animator文件夹,然后建立res/animator/scalex.xml
<?xml version="1.0" encoding="utf-8"?> <objectanimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:propertyname="scalex" android:valuefrom="1.0" android:valueto="2.0" android:valuetype="floattype" > </objectanimator>
代码:
public void scalex(view view) { // 加载动画 animator anim = animatorinflater.loadanimator(this, r.animator.scalex); anim.settarget(mmv); anim.start(); }
使用animatorinflater加载动画的资源文件,然后设置目标,就ok~~是不是很简单,这只是单纯横向的放大一倍~
如果我希望纵向与横向同时缩放呢?则可以怎么定义属性文件:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together" > <objectanimator android:duration="1000" android:propertyname="scalex" android:valuefrom="1" android:valueto="0.5" > </objectanimator> <objectanimator android:duration="1000" android:propertyname="scaley" android:valuefrom="1" android:valueto="0.5" > </objectanimator> </set>
使用set标签,有一个orderring属性设置为together,【还有另一个值:sequentially(表示一个接一个执行)】。
上篇博客中忽略了一个效果,就是缩放、反转等都有中心点或者轴,默认中心缩放,和中间对称线为反转线,所以我决定这个横向,纵向缩小以左上角为中心点:
代码:
// 加载动画 animator anim = animatorinflater.loadanimator(this, r.animator.scale); mmv.setpivotx(0); mmv.setpivoty(0); //显示的调用invalidate mmv.invalidate(); anim.settarget(mmv); anim.start();
很简单,直接给view设置pivotx和pivoty,然后调用一下invalidate,就ok了。
下面看效果图:
好了,通过写xml声明动画,使用set嵌套set,结合orderring属性,也基本可以实现任何动画~~上面也演示了pivot的设置。
2、布局动画(layout animations)
主要使用layouttransition为布局的容器设置动画,当容器中的视图层次发生变化时存在过渡的动画效果。
基本代码为:
layouttransition transition = new layouttransition(); transition.setanimator(layouttransition.change_appearing, transition.getanimator(layouttransition.change_appearing)); transition.setanimator(layouttransition.appearing, null); transition.setanimator(layouttransition.disappearing, null); transition.setanimator(layouttransition.change_disappearing, null); mgridlayout.setlayouttransition(transition);
过渡的类型一共有四种:
(1)layouttransition.appearing 当一个view在viewgroup中出现时,对此view设置的动画
(2)layouttransition.change_appearing 当一个view在viewgroup中出现时,对此view对其他view位置造成影响,对其他view设置的动画
(3)layouttransition.disappearing 当一个view在viewgroup中消失时,对此view设置的动画
(4)layouttransition.change_disappearing 当一个view在viewgroup中消失时,对此view对其他view位置造成影响,对其他view设置的动画
(5)layouttransition.change 不是由于view出现或消失造成对其他view位置造成影响,然后对其他view设置的动画。
注意动画到底设置在谁身上,此view还是其他view。
好了下面看一个综合的例子:
布局文件:
<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" > <button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onclick="addbtn" android:text="addbtns" /> <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>
代码:
package com.example.zhy_property_animation; import android.animation.layouttransition; import android.app.activity; import android.os.bundle; import android.view.view; import android.view.view.onclicklistener; import android.view.viewgroup; import android.widget.button; import android.widget.checkbox; import android.widget.compoundbutton; import android.widget.compoundbutton.oncheckedchangelistener; import android.widget.gridlayout; public class layoutanimaactivity extends activity implements oncheckedchangelistener { private viewgroup viewgroup; private gridlayout mgridlayout; private int mval; private layouttransition mtransition; private checkbox mappear, mchangeappear, mdisappear, mchangedisappear; @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.layout_animator); viewgroup = (viewgroup) findviewbyid(r.id.id_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); mappear.setoncheckedchangelistener(this); mchangeappear.setoncheckedchangelistener(this); mdisappear.setoncheckedchangelistener(this); mchangedisappear.setoncheckedchangelistener(this); // 创建一个gridlayout mgridlayout = new gridlayout(this); // 设置每列5个按钮 mgridlayout.setcolumncount(5); // 添加到布局中 viewgroup.addview(mgridlayout); //默认动画全部开启 mtransition = new layouttransition(); mgridlayout.setlayouttransition(mtransition); } /** * 添加按钮 * * @param view */ public void addbtn(view view) { final button button = new button(this); button.settext((++mval) + ""); mgridlayout.addview(button, math.min(1, mgridlayout.getchildcount())); button.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { mgridlayout.removeview(button); } }); } @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); } }
效果图:
动画有点长,耐心点看,一定要注意,是对当前view还是其他views设置的动画。
当然了动画支持自定义,还支持设置时间,比如我们修改下,添加的动画为:
mtransition.setanimator(layouttransition.appearing, (mappear .ischecked() ? objectanimator.offloat(this, "scalex", 0, 1) : null));
则效果为:
原本的淡入,变成了宽度从中间放大的效果~~是不是还不错~~
3、view的anim方法
在sdk11的时候,给view添加了animate方法,更加方便的实现动画效果。
布局文件:
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <imageview android:id="@+id/id_ball" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/bol_blue" /> <linearlayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignparentbottom="true" android:orientation="horizontal" > <button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onclick="viewanim" android:text="view anim" /> <button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onclick="propertyvaluesholder" android:text="propertyvaluesholder " /> </linearlayout> </relativelayout>
代码:
package com.example.zhy_property_animation; import android.animation.objectanimator; import android.animation.propertyvaluesholder; import android.app.activity; import android.os.bundle; import android.util.displaymetrics; import android.util.log; import android.view.view; import android.widget.imageview; public class viewanimateactivity extends activity { protected static final string tag = "viewanimateactivity"; private imageview mblueball; private float mscreenheight; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.view_animator); displaymetrics outmetrics = new displaymetrics(); getwindowmanager().getdefaultdisplay().getmetrics(outmetrics); mscreenheight = outmetrics.heightpixels; mblueball = (imageview) findviewbyid(r.id.id_ball); } public void viewanim(view view) { // need api12 mblueball.animate()// .alpha(0)// .y(mscreenheight / 2).setduration(1000) // need api 12 .withstartaction(new runnable() { @override public void run() { log.e(tag, "start"); } // need api 16 }).withendaction(new runnable() { @override public void run() { log.e(tag, "end"); runonuithread(new runnable() { @override public void run() { mblueball.sety(0); mblueball.setalpha(1.0f); } }); } }).start(); } }
简单的使用mblueball.animate().alpha(0).y(mscreenheight / 2).setduration(1000).start()就能实现动画~~不过需要sdk11,此后在sdk12,sdk16又分别添加了withstartaction和withendaction用于在动画前,和动画后执行一些操作。当然也可以.setlistener(listener)等操作。
使用objectanimator实现上面的变化,我们可以使用:propertyvalueholder
propertyvaluesholder pvhx = propertyvaluesholder.offloat("alpha", 1f, 0f, 1f); propertyvaluesholder pvhy = propertyvaluesholder.offloat("y", 0, mscreenheight / 2, 0); objectanimator.ofpropertyvaluesholder(mblueball, pvhx, pvhy).setduration(1000).start();
效果与上面一样。
运行结果:
推荐阅读
-
Android中Property Animation属性动画编写的实例教程
-
Android中编写属性动画PropertyAnimation的进阶实例
-
Android中编写简单的手电筒小应用的实例教程
-
Android系统中的蓝牙连接程序编写实例教程
-
解析Android中Animation动画的编写要点
-
Android中简单的电话管理与短信管理App编写实例
-
实例讲解Android中ViewPager组件的一些进阶使用技巧
-
Android中编写属性动画PropertyAnimation的进阶实例
-
Android中Property Animation属性动画编写的实例教程
-
Android中编写简单的手电筒小应用的实例教程