随笔-145  评论-173  文章-70  trackbacks-0

1.基本动画使用方式

在包com.example.android.apis.view下面的Animation13有各种使用方式,分别来进行介绍。

Animation1.java 如下所示(原始代码在包com.example.android.apis.view下面)

package com.example.android.apis.view;

// Need the following import to get access to the app resources, since this

// class is in a sub-package.

import com.example.android.apis.R;


import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.animation.Animation;

import android.view.animation.AnimationUtils;


public class Animation1 extends Activity implements View.OnClickListener {


@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.animation_1);


View loginButton = findViewById(R.id.login);

loginButton.setOnClickListener(this);

}


public void onClick(View v) {

Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);

findViewById(R.id.pw).startAnimation(shake);

}

R.layout.animation_1对应的XML文件为:

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

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

android:orientation="vertical"

android:padding="10dip"

android:layout_width="match_parent"

android:layout_height="wrap_content">

<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginBottom="10dip"

android:text="@string/animation_1_instructions"

/>

<EditText android:id="@+id/pw"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:clickable="true"

android:singleLine="true"

android:password="true"

/>


<Button android:id="@+id/login"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/googlelogin_login"

/>


</LinearLayout>

XML文件为程序的主运行界面。如何实现动画呢?

实际上实现动画有两种方式,一种是在代码中构造Animation对象,一种是在XML文件中定义相关的资源。

如果构造对象,则应该分别新建AlphaAnimation等对象,而如果是XML文件中,则应该使用alpha等标签。在本例中,使用的是XML文件来创建Animation对象。

XML

alpha 渐变透明度动画效果

scale 渐变尺寸伸缩动画效果

translate 画面转换位置移动动画效果

rotate 画面转移旋转动画效果

JavaCode

AlphaAnimation 渐变透明度动画效果

ScaleAnimation 渐变尺寸伸缩动画效果

TranslateAnimation 画面转换位置移动动画效果

RotateAnimation 画面转移旋转动画效果

OnCreate函数中,通过绑定Button实现对按钮事件的监听。

onClick函数中,定义了点击按钮时候触发的动作,这里面的代码即实现相应的特效的代码。从代码中可以看到,这里首先执行下面的代码:

Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);

findViewById(R.id.pw).startAnimation(shake);

在这段代码中,通过loadAnimation函数来载入动画元素,而动画资源则是在R.anim.shake中定义。找到该XML文件,内容如下:

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

<translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="0"

android:toXDelta="10"

android:duration="1000"

android:interpolator="@anim/cycle_7"

/>

从中可以看到,该XML文件中,通过标签tranlate来定义平移的动作,并且设定了相关的参数,另外,注意其中的interpolator参数,该参数的设定是通过另外一个XML文件cycle_7来设定的。内容如下:

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

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

android:cycles="7" />

至此,完成了动画的Animation,即参数的设定,最终就是调用AnimationUtils.loadAnimation来创建Animation对象shake,然后通过某个View的字函数startAnimation在该View上启动该动画。

比如这里:

findViewById(R.id.pw).startAnimation(shake);

首先获得的是password的那个EditTextView,然后在该View上调用startAnimation方法,启动shake这种动画。效果就是点击login登录按钮后,password的编辑框会出现来回抖动的效果。

既然弄清楚了Animation的两种使用方法,并且在上面中通过剖析AndroidAPI Demo了解了使用XML来实现动画效果的例子,那么下面我们自己动手,利用Java Code的办法,实现同样的效果。

具体过程如下:

  1. 首先新建一个Android项目功能,然后编辑main.xml文件,添加一个ButtonEditText控件,实现类似的原来那个例子那样的控件效果。

  2. 编辑OnCreate函数,在代码中实现前面的这些效果。

代码如下:

import android.app.Activity;

import android.app.SearchManager.OnCancelListener;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.view.animation.Animation;

import android.view.animation.AnimationUtils;

import android.view.animation.CycleInterpolator;

import android.view.animation.Interpolator;

import android.view.animation.TranslateAnimation;


public class AnimationTest extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

View login = findViewById(R.id.login);

login.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

TranslateAnimation ta = new TranslateAnimation(0, 10, 0, 0);

ta.setDuration(1000);

ta.setInterpolator(new CycleInterpolator(7));

findViewById(R.id.passwd).startAnimation(ta);

}

});

}

}

  1. 运行该工程后,就能够达到和Demo例子中同样的效果。

  2. 代码解读:

其实功能很简单,原始Demo是通过loadAnimation函数读取XML文件,那么我们只需要新建对应的Animation对象就行了。原始例子中使用的是Translate标签,对应的就是TranslateAnimation类,为此新建该对象,设定的参数就是原XML文件中的fromXDeltatoXDelta等等,由于原来的标签没有设定Y方向上的参数,所以使用默认的00.然后观察发现原始还是用了一个cycleInterpolatorXML资源,其中定义了一个cycle值,为此同样找到Java Code对应的类,new一个这样的对象并设定参数。最终同样的对密码控件实现该特效效果,达到同样的效果。

2.利用XML来定义动画

在分析完上面这个最基本的动画特效使用之后,下面继续分析API Demo中剩余的两个例子,它们分别是位于com.example.android.apis.view包下面的Animation2.javaAnimation3.java文件。

首先分析Animation2.java对应的工程,原文件如下。

package com.example.android.apis.view;


// Need the following import to get access to the app resources, since this

// class is in a sub-package.

import com.example.android.apis.R;


import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.animation.AnimationUtils;

import android.widget.AdapterView;

import android.widget.ArrayAdapter;

import android.widget.Spinner;

import android.widget.ViewFlipper;



public class Animation2 extends Activity implements

AdapterView.OnItemSelectedListener {


@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.animation_2);


mFlipper = ((ViewFlipper) this.findViewById(R.id.flipper));

mFlipper.startFlipping();


Spinner s = (Spinner) findViewById(R.id.spinner);

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,

android.R.layout.simple_spinner_item, mStrings);

adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

s.setAdapter(adapter);

s.setOnItemSelectedListener(this);

}


public void onItemSelected(AdapterView parent, View v, int position, long id) {

switch (position) {


case 0:

mFlipper.setInAnimation(AnimationUtils.loadAnimation(this,

R.anim.push_up_in));

mFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,

R.anim.push_up_out));

break;

case 1:

mFlipper.setInAnimation(AnimationUtils.loadAnimation(this,

R.anim.push_left_in));

mFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,

R.anim.push_left_out));

break;

case 2:

mFlipper.setInAnimation(AnimationUtils.loadAnimation(this,

android.R.anim.fade_in));

mFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,

android.R.anim.fade_out));

break;

default:

mFlipper.setInAnimation(AnimationUtils.loadAnimation(this,

R.anim.hyperspace_in));

mFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,

R.anim.hyperspace_out));

break;

}

}


public void onNothingSelected(AdapterView parent) {

}


private String[] mStrings = {

"Push up", "Push left", "Cross fade", "Hyperspace"};


private ViewFlipper mFlipper;


}

从代码中可以看到,该类有一个ViewFlipper类型的成员变量,以及定义了菜单项的字符串数组。在OnCreate函数中,首先设定程序的主界面布局为animation_2.xml文件,该文件的内容如下:

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

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

android:orientation="vertical"

android:padding="10dip"

android:layout_width="match_parent"

android:layout_height="wrap_content">


<ViewFlipper android:id="@+id/flipper"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:flipInterval="2000"

android:layout_marginBottom="20dip" >

<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="center_horizontal"

android:textSize="26sp"

android:text="@string/animation_2_text_1"/>

<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="center_horizontal"

android:textSize="26sp"

android:text="@string/animation_2_text_2"/>

<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="center_horizontal"

android:textSize="26sp"

android:text="@string/animation_2_text_3"/>

<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="center_horizontal"

android:textSize="26sp"

android:text="@string/animation_2_text_4"/>

</ViewFlipper>


<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginBottom="5dip"

android:text="@string/animation_2_instructions"

/>


<Spinner android:id="@+id/spinner"

android:layout_width="match_parent"

android:layout_height="wrap_content"

/>


</LinearLayout>



从该XML文件中可以看到主界面的组成,一个ViewFlipper控件,一个显示提示信息的TextView,以及一个Spinner控件。所谓的ViewFlipper是一个多View的集合,但是每次都只能够显示出一个View,从最终的动画效果可以看到,该ViewFlipper中的每一个TextView,都以事先定义的某种动画形式不断的切换,轮流的显示出来。Spinner则是一个选择菜单,点击后出现下拉菜单,让用户选择某个选项,在这里,每一个选项的内容就是数组mStrings的内容。


2-1 Spinner 的效果

最终的效果就是,用户通过点击Spinner中的某个选项,可以选择不同的效果。而上方的那个ViewFlipper则以该种动画效果轮流显示出每一个TextViewViewFlipper的四个子TextView得以轮流动画显示,消失。

OnCreate函数中,首先获得ViewFlipper控件,然后通过调用startFlipping函数,开启一个计时器来循环显示出子View。此后,获得Spinner控件,然后利用mString数组创建一个ArrayAdapter,并指定为该SpinnerAdapter,最后,调用setOnItemSelectedListener开启一个监听选项的监听器,每当选择不同的选项时,进入不同的处理过程。

在分析完OnCreate函数后,整个工程就剩下选项被选中时候的函数实现了,即onItemSelected函数,当程序启动后OnCreate函数中添加了监视器,开始监听。用户一点点击选择了某个选项,就会根据这个position来进入不同的处理过程中。从代码中可以看到,switch……case的结构,分别针对用户选择 "Push up", "Push left", "Cross fade", "Hyperspace"

这四个菜单时候的动作,在每个选项中的动作类似,因此只针对第一个进行介绍。

case 0:

mFlipper.setInAnimation(AnimationUtils.loadAnimation(this,

R.anim.push_up_in));

mFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,

R.anim.push_up_out));

break;

在用户选择了第一个Push Up菜单后,该ViewFlipper通过使用setInAnimation函数来设定一个进入到屏幕中的View的动画(Specifies the animation used to animate a View that enters the screen.)通过使用setOutAnimation来指定一个离开屏幕时候的View的动画(Specifies the animation used to animate a View that exit the screen.)这两个函数的参数都是一个Animation类型的对象,在前面第一部分的讲解中知道,有两种办法可以得到该对象。

  1. XML 文件中定义,利用AnimationUtils.loadAnimation来载入该动画

  2. 利用Java CodeAnimation类来创建各种类型的对象。

在这里,使用的是第一种办法。查看相应的XML文件。

push_up_in.xml 文件

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

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

<translate android:fromYDelta="100%p" android:toYDelta="0" android:duration="300"/>

<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" />

</set>

从代码中可以看到,这是一个动画集合,包括一个translate,即平移动画,以及一个alpha,即透明度渐变的动画。在标签中分别设定了变化的参数,持续的时间等等。

从代码以及最终的运行效果可以知道,该动画特效就是,进入的时候从Y轴坐标100变化到0,即从下往上进入屏幕,透明度从0变为1,即从开始的不可见,逐渐变的清晰可见。类似的,push_up_out则实现相反的效果,在XML文件中有相应的表示。

同理,push_up_out.xml文件也可以采用类似的方法分析。

至此,我们分析完了第二个工程,对整个动画如何实现,如何正确的调用Animation函数都有了一个更清晰的认识。

3.利用JavaCode来实现动画

最后,我们简单来分析下第三个工程,因为上面两个工程的分析,最后一个的实现机制也是类似的。

Animation3.java


package com.example.android.apis.view;


// Need the following import to get access to the app resources, since this

// class is in a sub-package.

import com.example.android.apis.R;


import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.animation.AnimationUtils;

import android.view.animation.Animation;

import android.view.animation.TranslateAnimation;

import android.widget.AdapterView;

import android.widget.ArrayAdapter;

import android.widget.Spinner;


public class Animation3 extends Activity implements AdapterView.OnItemSelectedListener {

private static final String[] INTERPOLATORS = {

"Accelerate", "Decelerate", "Accelerate/Decelerate",

"Anticipate", "Overshoot", "Anticipate/Overshoot",

"Bounce"

};


@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.animation_3);


Spinner s = (Spinner) findViewById(R.id.spinner);

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,

android.R.layout.simple_spinner_item, INTERPOLATORS);

adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

s.setAdapter(adapter);

s.setOnItemSelectedListener(this);

}


public void onItemSelected(AdapterView parent, View v, int position, long id) {

final View target = findViewById(R.id.target);

final View targetParent = (View) target.getParent();


Animation a = new TranslateAnimation(0.0f,

targetParent.getWidth() - target.getWidth() - targetParent.getPaddingLeft() -

targetParent.getPaddingRight(), 0.0f, 0.0f);

a.setDuration(1000);

a.setStartOffset(300);

a.setRepeatMode(Animation.RESTART);

a.setRepeatCount(Animation.INFINITE);


switch (position) {

case 0:

a.setInterpolator(AnimationUtils.loadInterpolator(this,

android.R.anim.accelerate_interpolator));

break;

case 1:

a.setInterpolator(AnimationUtils.loadInterpolator(this,

android.R.anim.decelerate_interpolator));

break;

case 2:

a.setInterpolator(AnimationUtils.loadInterpolator(this,

android.R.anim.accelerate_decelerate_interpolator));

break;

case 3:

a.setInterpolator(AnimationUtils.loadInterpolator(this,

android.R.anim.anticipate_interpolator));

break;

case 4:

a.setInterpolator(AnimationUtils.loadInterpolator(this,

android.R.anim.overshoot_interpolator));

break;

case 5:

a.setInterpolator(AnimationUtils.loadInterpolator(this,

android.R.anim.anticipate_overshoot_interpolator));

break;

case 6:

a.setInterpolator(AnimationUtils.loadInterpolator(this,

android.R.anim.bounce_interpolator));

break;

}


target.startAnimation(a);

}


public void onNothingSelected(AdapterView parent) {

}

}

同工程2,在OnCreate函数中,设定了程序运行的主界面的layout,包括两个TextView和一个SpinnerSpinner同样是一个选择菜单,两个TextView中,一个是显示的标签,保持不变,另外一个实现动画特效的View

Animation3.xml文件:

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


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

android:orientation="vertical"

android:padding="10dip"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:clipToPadding="false">


<TextView

android:id="@+id/target"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:textSize="26sp"

android:text="@string/animation_3_text"/>


<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="20dip"

android:layout_marginBottom="5dip"

android:text="@string/animation_2_instructions" />


<Spinner

android:id="@+id/spinner"

android:layout_width="match_parent"

android:layout_height="wrap_content" />


</LinearLayout>


3-1 Spinner选项

回到代码中,当用户选择某个选项时,进入到onItemSelected函数,此时获得带显示动画特效的那个TextView的引用以及它的父View,然后新建一个Animatioin,注意此处没有通过XML文件来定义,而是利用Java Code来创建动画特效。通过设置各种参数,定义特效的实现形式。其中下面的代码需要注意:

Animation a = new TranslateAnimation(0.0f,

targetParent.getWidth()-target.getWidth()-targetParent.getPaddingLeft() -

targetParent.getPaddingRight(),0.0f, 0.0f);</LinearLayout>

为何要使用targetParent来计算长宽,而不是直接使用自己这个TextView呢?原因在于,该TextView是位于整个layout中的,而待实现的这个特效,实际上是要这个TextView在父layout上面左右移动(或者是其他运行形式),所以,运动的范围要局限在父对象中,因此是使用targetParent而不是target来设定该Animation

余下的工作就是设定各种参数,对于本函数中的Swtich……case,则只是起到了修改Interpolator的作用,用户在选中不同的Interpolator后,该TextView将采用不同的形式来运动,那么,何为Interpolator对象呢?

SDK中的解释再清楚不过了:

" An interpolator defines the rate of change of an animation. This allows the basic animation effects (alpha, scale, translate, rotate) to be accelerated, decelerated, repeated, etc."

也就是说Interpolator是一个定义了动画变化的快慢速率的东西,它允许定义基本的动画效果为加速,减速或者重复显示等等效果。

最后,完成了上面的工作后,通过调用target.startAnimation(a);来使得target这个TextView按照设定的动画效果a进行变换显示。

最后做一个总结:实现动画的方式有两种:XML和JavaCode,还有,学习使用的最好办法是看Sample,查SDK文档,虽然初看Sample可能觉得有些困难,但是慢慢查文档,遇到复杂的用法和控件就先查查文档看看有没有,或者Google之,慢慢就会明白了。还有,学习之余多进行变化,比如换种方式实现,或者注释掉某行代码,再查看效果,即可对关键点有一个更清晰的了解。



posted on 2011-10-22 10:27 deercoder 阅读(4808) 评论(0)  编辑 收藏 引用 所属分类: Android

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理