转载请注明出处:http://blog.csdn.net/yegongheng/article/details/38435553
上一篇博文我们初步地了解了Property Animation的工作方式及流程,并通过实验加深了对对象属性计算过程的理解,同时,我在文章的最后罗列一些实现Property Animation比较重要的类、接口和方法,并做了比较详细地说明。那今天这篇文章,我将带领大家使用这些Android系统提供的API来实现一些比较炫的动画效果。
ValueAnimator是Property Animation系统的核心类,它包含了配置Property Animation属性的大部分方法,那要实现一个Property Animation,都需要直接或间接使用ValueAnimator类。那接下来我们将借助ValueAnimator类提供的方法来实现各种各样的动画效果,不过在此之前我们来学习一下实现动画的几个关键知识点。
public class CustomInterpolator implements TimeInterpolator {
@Override
public float getInterpolation(float input) {
// 编写相关的逻辑计算
//input *= 0.8f;
return input * input;
}
}
上面是一个简单的示例,我们要实现一个自定义的Interpolator,只需在方法中编写相关的罗就计算就行。
import android.animation.TypeEvaluator;
import android.annotation.SuppressLint;
@SuppressLint("NewApi")
public class CustomEvaluator implements TypeEvaluator {
@Override
public Float evaluate(float fraction, Number startValue, Number endValue) {
// TODO Auto-generated method stub
float propertyResult = 0;
/*float startFloat = startValue.floatValue();
return (startFloat + fraction * (endValue.floatValue() - startFloat));*/
return propertyResult;
}
}
那一般使用ValueAnimator实现动画分为以下七个步骤:
1. 调用ValueAnimation类中的ofInt(int...values)、ofFloat(String propertyName,float...values)等静态方法实例化ValueAnimator对象,并设置目标属性的属性名、初始值或结束值等值;
2.调用addUpdateListener(AnimatorUpdateListener mListener)方法为ValueAnimator对象设置属性变化的监听器;
3.创建自定义的Interpolator,调用setInterpolator(TimeInterpolator value)为ValueAniamtor设置自定义的Interpolator;(可选,不设置默认为缺省值)
4.创建自定义的TypeEvaluator,调用setEvaluator(TypeEvaluator value)为ValueAnimator设置自定义的TypeEvaluator;(可选,不设置默认为缺省值)
5.在AnimatorUpdateListener 中的实现方法为目标对象的属性设置计算好的属性值。
6.设置动画的持续时间、是否重复及重复次数等属性;
7.为ValueAnimator设置目标对象并开始执行动画。
/**
* 使用ValueAnimator改变Imageview的margin的值
*/
public void marginValueAnimator(){
//1.调用ofInt(int...values)方法创建ValueAnimator对象
ValueAnimator mAnimator = ValueAnimator.ofInt(0,screenWidth - mImageViewTest.getWidth());
//2.为目标对象的属性变化设置监听器
mAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 3.为目标对象的属性设置计算好的属性值
int animatorValue = (int)animation.getAnimatedValue();
MarginLayoutParams marginLayoutParams = (MarginLayoutParams) mImageViewTest.getLayoutParams();
marginLayoutParams.leftMargin = animatorValue;
mImageViewTest.setLayoutParams(marginLayoutParams);
}
});
//4.设置动画的持续时间、是否重复及重复次数等属性
mAnimator.setDuration(2000);
mAnimator.setRepeatCount(3);
mAnimator.setRepeatMode(ValueAnimator.REVERSE);
//5.为ValueAnimator设置目标对象并开始执行动画
mAnimator.setTarget(mImageViewTest);
mAnimator.start();
}
上面代码中,我们将属性的初始值、结束值分为设置为0和(屏幕宽度-ImageView控件的宽度),然后在监听方法中,通过调用getAnimationValue()获取动画在播放过程中属性值的变化情况,然后将属性值赋给ImageView对象的marginLeft。接着调用setXX()方法设置动画的相关属性,最后调用start()方法,执行动画。动画的实现流程和我们基本按照我们上面罗列的步骤基本一致,只不过没有设置Interpolator和TypeEvaluator,系统会自动默认为缺省。
ImageView的实例化代码和screenWidth屏幕宽度的获取代码在此不列出,具体的代码在文章末尾可以提供下载。
/**
* 使用ValueAnimator实现图片缩放动画
*/
public void scaleValueAnimator(){
//1.设置目标属性名及属性变化的初始值和结束值
PropertyValuesHolder mPropertyValuesHolderScaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f,0.0f);
PropertyValuesHolder mPropertyValuesHolderScaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f,0.0f);
ValueAnimator mAnimator = ValueAnimator.ofPropertyValuesHolder(mPropertyValuesHolderScaleX,mPropertyValuesHolderScaleY);
//2.为目标对象的属性变化设置监听器
mAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 3.根据属性名获取属性变化的值分别为ImageView目标对象设置X和Y轴的缩放值
float animatorValueScaleX = (float) animation.getAnimatedValue("scaleX");
float animatorValueScaleY = (float) animation.getAnimatedValue("scaleY");
mImageViewTest.setScaleX(animatorValueScaleX);
mImageViewTest.setScaleY(animatorValueScaleY);
}
});
//4.为ValueAnimator设置自定义的Interpolator
mAnimator.setInterpolator(new CustomInterpolator());
//5.设置动画的持续时间、是否重复及重复次数等属性
mAnimator.setDuration(2000);
mAnimator.setRepeatCount(3);
mAnimator.setRepeatMode(ValueAnimator.REVERSE);
//6.为ValueAnimator设置目标对象并开始执行动画
mAnimator.setTarget(mImageViewTest);
mAnimator.start();
}
上面代码列表中,我们通过PropertyValuesHolder类为目标属性名来设置属性值的初始值和结束值,然后ValueAnimator通过调用ofPropertyValuesHolder(PropertyValuesHolder...values)设置已经配置好的PropertyValuesHolder对象。不过需要注意的是使用
PropertyValuesHolder设置的属性必须是目标对象的属性中有setXX()方法才能进行设置,例如ImageView对象中有setScaleX()方法才能为ImageView设置对应属性的PropertyValuesHolder对象。接着ValueAnimator对象调用setInterpolator(TimeInterpolator value)设置自定义的Interpolator,类名为CustomInterpolator,具体的代码如下:
package com.androidleaf.animation.customproperty;
import android.animation.TimeInterpolator;
import android.annotation.SuppressLint;
@SuppressLint("NewApi")
public class CustomInterpolator implements TimeInterpolator {
@Override
public float getInterpolation(float input) {
input *= 0.8f;
return input * input;
}
}
接着,为ValueAnimator对象设置相应的属性,如动画重复次数、动画所持续的时间等等。最后,为ValueAnimator设置目标对象并启动动画。我们运行一下程序,看一下运行的效果图,如下:
/**
* 隐藏或显示ListView的动画
*/
public void hideOrShowListViewAnimator(final int startValue,final int endValue){
//1.设置属性的初始值和结束值
ValueAnimator mAnimator = ValueAnimator.ofInt(0,100);
//2.为目标对象的属性变化设置监听器
mAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// TODO Auto-generated method stub
int animatorValue = (int)animation.getAnimatedValue();
float fraction = animatorValue/100f;
IntEvaluator mEvaluator = new IntEvaluator();
//3.使用IntEvaluator计算属性值并赋值给ListView的高
mListView.getLayoutParams().height = mEvaluator.evaluate(fraction, startValue, endValue);
mListView.requestLayout();
}
});
//4.为ValueAnimator设置LinearInterpolator
mAnimator.setInterpolator(new LinearInterpolator());
//5.设置动画的持续时间
mAnimator.setDuration(500);
//6.为ValueAnimator设置目标对象并开始执行动画
mAnimator.setTarget(mListView);
mAnimator.start();
}
上面代码列表中,需传递的两个参数分别为属性值的初始值和结束值,当需要显示ListView时,传入0和800像素值,当需要隐藏ListView时,传入800和0像素值,ListView的初始化高度默认是0。运行程序,动画效果如下:
public class ObjectAnimatorFragment extends Fragment implements OnClickListener{
private ListView mListViewFront;
private ListView mListViewReverse;
private Button mButtonFlip;
private Button mButtonAlpha;
private Button mButtonScale;
private Button mButtonTranslate;
private Button mButtonRotate;
private Button mButtonSet;
private ImageView mImageView;
private int screenWidth = 0;
private int screenHeight = 0;
String[] frontStrs = {
"Front Page 1",
"Front Page 2",
"Front Page 3",
"Front Page 4",
"Front Page 5",
"Front Page 6",
};
String[] reverseStrs = {
"Reverse Page 1",
"Reverse Page 2",
"Reverse Page 3",
"Reverse Page 4",
"Reverse Page 5",
"Reverse Page 6",
};
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
float density = metrics.density;
//screenWidth = (int)(metrics.widthPixels * density + 0.5f);
//screenHeight = (int)(metrics.heightPixels * density + 0.5f);
screenWidth = metrics.widthPixels;
screenHeight = metrics.heightPixels;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View rootView = inflater.inflate(R.layout.fragment_objectanimator, container, false);
mListViewFront = (ListView) rootView.findViewById(R.id.front_page_listview);
mListViewReverse = (ListView) rootView.findViewById(R.id.reverse_page_listview);
mButtonFlip = (Button)rootView.findViewById(R.id.button_flip);
mButtonFlip.setOnClickListener(this);
mButtonAlpha = (Button)rootView.findViewById(R.id.button_alpha);
mButtonAlpha.setOnClickListener(this);
mButtonScale = (Button)rootView.findViewById(R.id.button_scale);
mButtonScale.setOnClickListener(this);
mButtonTranslate = (Button)rootView.findViewById(R.id.button_translate);
mButtonTranslate.setOnClickListener(this);
mButtonRotate = (Button)rootView.findViewById(R.id.button_rotate);
mButtonRotate.setOnClickListener(this);
mButtonSet = (Button)rootView.findViewById(R.id.button_set);
mButtonSet.setOnClickListener(this);
mImageView = (ImageView)rootView.findViewById(R.id.objectanimator_imageview);
mImageView.setOnClickListener(this);
initData();
return rootView;
}
public void initData(){
ArrayAdapter frontListData = new ArrayAdapter(getActivity(), R.layout.layout_objectanimator_item,R.id.objectanimtor_item_textview, frontStrs);
ArrayAdapter reverseListData = new ArrayAdapter(getActivity(), R.layout.layout_objectanimator_item,R.id.objectanimtor_item_textview, reverseStrs);
mListViewFront.setAdapter(frontListData);
mListViewReverse.setAdapter(reverseListData);
mListViewReverse.setRotationX(-90.0f);
}
@Override
public void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.button_flip:
flip();
break;
case R.id.button_alpha:
alphaAnimator();
break;
case R.id.button_scale:
scaleAnimator();
break;
case R.id.button_translate:
translateAniamtor();
break;
case R.id.button_rotate:
rotateAniamtor();
break;
case R.id.button_set:
setAnimator();
break;
case R.id.objectanimator_imageview:
mListViewFront.setVisibility(View.VISIBLE);
mImageView.setVisibility(View.GONE);
break;
default:
break;
}
}
/**
* 翻转动画效果
*/
public void flip(){
final ListView visibleView;
final ListView invisibleView;
if(mListViewFront.getVisibility() == View.GONE){
visibleView = mListViewReverse;
invisibleView = mListViewFront;
}else{
visibleView = mListViewFront;
invisibleView = mListViewReverse;
}
//创建ListView从Visible到Gone的动画
ObjectAnimator visibleToInVisable = ObjectAnimator.ofFloat(visibleView, "rotationX", 0.0f,90.0f);
//设置插值器
visibleToInVisable.setInterpolator(new AccelerateInterpolator());
visibleToInVisable.setDuration(500);
//创建ListView从Gone到Visible的动画
final ObjectAnimator invisibleToVisible = ObjectAnimator.ofFloat(invisibleView, "rotationX", -90.0f,0.0f);
//设置插值器
invisibleToVisible.setInterpolator(new DecelerateInterpolator());
invisibleToVisible.setDuration(500);
visibleToInVisable.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// TODO Auto-generated method stub
super.onAnimationEnd(animation);
visibleView.setVisibility(View.GONE);
invisibleToVisible.start();
invisibleView.setVisibility(View.VISIBLE);
}
});
visibleToInVisable.start();
}
/**
* 渐变动画效果
*/
public void alphaAnimator(){
ListView alphaListView = null;
if(mListViewFront.getVisibility() == View.GONE){
alphaListView = mListViewReverse;
}else{
alphaListView = mListViewFront;
}
//1、通过调用ofFloat()方法创建ObjectAnimator对象,并设置目标对象、需要改变的目标属性名、初始值和结束值;
ObjectAnimator mAnimatorAlpha = ObjectAnimator.ofFloat(alphaListView, "alpha", 1.0f,0.0f);
//2、设置动画的持续时间、是否重复及重复次数属性;
mAnimatorAlpha.setRepeatMode(Animation.REVERSE);
mAnimatorAlpha.setRepeatCount(3);
mAnimatorAlpha.setDuration(1000);
//3、启动动画
mAnimatorAlpha.start();
}
/**
* 伸缩动画效果
*/
public void scaleAnimator(){
ListView scaleListView = null;
if(mListViewFront.getVisibility() == View.GONE){
scaleListView = mListViewReverse;
}else{
scaleListView = mListViewFront;
}
ObjectAnimator mAnimatorScaleX = ObjectAnimator.ofFloat(scaleListView, "scaleX", 1.0f,0.0f);
mAnimatorScaleX.setRepeatMode(Animation.REVERSE);
mAnimatorScaleX.setRepeatCount(3);
mAnimatorScaleX.setDuration(1000);
ObjectAnimator mAnimatorScaleY = ObjectAnimator.ofFloat(scaleListView, "scaleY", 1.0f,0.0f);
mAnimatorScaleY.setRepeatMode(Animation.REVERSE);
mAnimatorScaleY.setRepeatCount(3);
mAnimatorScaleY.setDuration(1000);
mAnimatorScaleX.start();
mAnimatorScaleY.start();
}
/**
* 位移动画效果
*/
public void translateAniamtor(){
ListView translateListView = null;
if(mListViewFront.getVisibility() == View.GONE){
translateListView = mListViewReverse;
}else{
translateListView = mListViewFront;
}
ObjectAnimator mAnimatorTranslateX = ObjectAnimator.ofFloat(translateListView, "translationX", 0.0f,screenWidth/2);
mAnimatorTranslateX.setRepeatMode(Animation.REVERSE);
mAnimatorTranslateX.setRepeatCount(3);
mAnimatorTranslateX.setDuration(1000);
ObjectAnimator mAnimatorTranslateY = ObjectAnimator.ofFloat(translateListView, "translationY", 0.0f,screenHeight/2);
mAnimatorTranslateY.setRepeatMode(Animation.REVERSE);
mAnimatorTranslateY.setRepeatCount(3);
mAnimatorTranslateY.setDuration(1000);
mAnimatorTranslateX.start();
mAnimatorTranslateY.start();
}
/**
* 旋转动画效果
*/
public void rotateAniamtor(){
ListView rotateListView = null;
if(mListViewFront.getVisibility() == View.GONE){
rotateListView = mListViewReverse;
}else{
rotateListView = mListViewFront;
}
ObjectAnimator mAnimatorRotate = ObjectAnimator.ofFloat(rotateListView, "rotation", 0.0f,360.0f);
mAnimatorRotate.setRepeatMode(Animation.REVERSE);
mAnimatorRotate.setRepeatCount(2);
mAnimatorRotate.setDuration(2000);
mAnimatorRotate.start();
}
/**
* 动画集合
*/
public void setAnimator(){
ListView setListView = null;
if(mListViewFront.getVisibility() == View.GONE){
setListView = mListViewReverse;
}else{
setListView = mListViewFront;
}
setListView.setVisibility(View.GONE);
if(mImageView.getVisibility() == View.GONE){
mImageView.setVisibility(View.VISIBLE);
}
//代码方式设置动画
codeAnimatorSet(mImageView);
//用ViewPropertyAnimator实现动画
//viewPropertyAnimator(setListView);
//加载XML文件中的动画
/*AnimatorSet mAnimatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(getActivity(), R.animator.property_animation_animatorset);
mAnimatorSet.setTarget(mImageView);
mAnimatorSet.start();*/
}
/**
* 使用编码方式实现动画效果
* @param mImageView
*/
public void codeAnimatorSet(ImageView mImageView){
AnimatorSet mAnimatorSet = new AnimatorSet();
ObjectAnimator mAnimatorSetRotateX = ObjectAnimator.ofFloat(mImageView, "rotationX", 0.0f,360.0f);
mAnimatorSetRotateX.setDuration(3000);
ObjectAnimator mAnimatorSetRotateY = ObjectAnimator.ofFloat(mImageView, "rotationY", 0.0f,360.0f);
mAnimatorSetRotateY.setDuration(3000);
ObjectAnimator mAnimatorScaleX = ObjectAnimator.ofFloat(mImageView, "scaleX", 1.0f,0.5f);
mAnimatorScaleX.setRepeatCount(1);
mAnimatorScaleX.setRepeatMode(Animation.REVERSE);
mAnimatorScaleX.setDuration(1500);
ObjectAnimator mAnimatorScaleY = ObjectAnimator.ofFloat(mImageView, "scaleY", 1.0f,0.5f);
mAnimatorScaleY.setRepeatCount(1);
mAnimatorScaleY.setRepeatMode(Animation.REVERSE);
mAnimatorScaleY.setDuration(1500);
mAnimatorSet.play(mAnimatorSetRotateY).with(mAnimatorScaleX);
mAnimatorSet.play(mAnimatorScaleX).with(mAnimatorScaleY);
mAnimatorSet.play(mAnimatorSetRotateY).before(mAnimatorSetRotateX);
mAnimatorSet.start();
}
public void viewPropertyAnimator(ListView mListViewHolder){
mListViewHolder.animate().cancel();
mListViewHolder.animate().rotationX(360.0f).setDuration(3000).start();
}
}
代码量有些多,不过每个方法都有注释,而且逻辑也比较简单,所以不难理解,只要读者花点时间研究一下就可以很好的掌握。那接下来我们运行程序,运行及操作效果图如下:
源代码下载,请戳下面: