当前位置: 移动技术网 > IT编程>移动开发>Android > Android中编写属性动画PropertyAnimation的进阶实例

Android中编写属性动画PropertyAnimation的进阶实例

2019年07月24日  | 移动技术网IT编程  | 我要评论

陈瑀希,王健林是谁女婿,永城信息搜

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了。
下面看效果图:

2016419145721361.gif (733×398)

好了,通过写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); 
  } 
} 

效果图:

2016419145837034.gif (422×670)

动画有点长,耐心点看,一定要注意,是对当前view还是其他views设置的动画。
当然了动画支持自定义,还支持设置时间,比如我们修改下,添加的动画为:

mtransition.setanimator(layouttransition.appearing, (mappear 
        .ischecked() ? objectanimator.offloat(this, "scalex", 0, 1) 
        : null)); 

则效果为:

2016419145900874.gif (406×346)

原本的淡入,变成了宽度从中间放大的效果~~是不是还不错~~

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

效果与上面一样。
运行结果:

2016419150021670.gif (793×406)

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网