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

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
, 安卓
, 动画
, 属性动画
PropertyAnimation
property animation、qpropertyanimation、capropertyanimation、qpropertyanimation类、css动画animation实例,以便于您获取更多的相关知识。

时间: 2024-09-16 10:18:55

Android中编写属性动画PropertyAnimation的进阶实例_Android的相关文章

Android中使用Service实现后台发送邮件功能实例_Android

本文实例讲述了Android中使用Service实现后台发送邮件功能.分享给大家供大家参考,具体如下: 程序如下: import android.app.Activity; import android.content.Intent; import android.content.res.Resources.NotFoundException; import android.os.Bundle; import android.widget.TextView; public class A05Ac

Android中创建一个透明的进度对话框实例_Android

首先我们看一下什么叫做透明的进度对话框: 接下来我们讲一下如何创建:1.使用Eclipse创建一个新的Andr​​oid 项目,使用Android 2.2或以上.2.在/res/layout文件夹,创建线性布局activity_main.xml文件,主要是为了添加一个文本标签和一个按钮 复制代码 代码如下: activity_main.xml<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&quo

android中webview控件和javascript交互实例_Android

当我们要实现丰富的图文混排效果的时候,我们一般会使用webview,这是一个功能十分强大的的控件,来看看官方的解释: 复制代码 代码如下: A View that displays web pages. This class is the basis upon which you can roll your own web browser or simply display some online content within your Activity. It uses the WebKit

Android中ViewPager的PagerTabStrip与PagerTitleStrip用法实例_Android

零.概览1.ViewPager说白了就是个控件,在使用时包名要带全是Android.support.v4.view.ViewPager.由于我的ADT-Bundle版本比较高,这个包默认自带了,且默认是随apk打包导出的.如下图: 如果在Android Private Libraries里没这个包,则要自己在属性的Libraries里自己添加.添加后记得在上图所示的Order and Export里将其打勾. 2.理论上说要实现滑屏只要一个ViewPager就可以了,不需要再在里面嵌套如下: <

android中WebView和javascript实现数据交互实例_Android

在看懂这篇文章之前首先要有javascript基础. (1) js调用android的方法: 复制代码 代码如下: WebView wView: wView. addJavascriptInterface (Object obj, String interfaceName); 是实例化一个对象,在html的js中调用,第二个参数是实例化对象的别名,如果要使用这个obj,则在js中使用的名字 就是interfaceName. 复制代码 代码如下: public class jsWebDemo ex

Android中通过反射实现圆角ImageView代码实例_Android

private void init(){ paint = new Paint(Paint.ANTI_ALIAS_FLAG); roundRect = new RectF(0, 0, getWidth() , getHeight()); radius = 40; mPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN) ; } 继承ImageView,在构造方法中调用,初始化Paint和Xfermode. protec

android中把文件保存到sdcard代码实例_Android

直接上代码: package com.example.test; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import andr

Android 中HttpURLConnection与HttpClient使用的简单实例_Android

1:HttpHelper.java 复制代码 代码如下: public class HttpHelper {    //1:标准的Java接口    public static String getStringFromNet1(String param){        String result="";        try{            URL url=new URL(param);            HttpURLConnection conn=(HttpURLCo

Android中的广播和广播接收器代码实例_Android

BroadcastReceiver不仅可以接收系统广播,也可接收自定义的广播  1.定义一个广播接收器 复制代码 代码如下: public class MyReceiver extends BroadcastReceiver {          public MyReceiver()          {                    Log.i(TAG,"MyReceiver");          }                  //可用Intent的getActi