android Animation介绍
1、创建Animation对象
Animation animation = new Animation(){ @Override protected void applyTransformation(float interpolatedTime, Transformation t) { super.applyTransformation(interpolatedTime, t); Log.d("zgx","interpolatedTime=========="+interpolatedTime);Log.d("zgx","getAlpha==============="+t.getAlpha());Log.d("zgx","getTransformationType======="+t.getTransformationType()); Log.d("zgx","getMatrix==============="+t.getMatrix()); }}
从上面代码我们可以看到,每个动画都重载了父类的applyTransformation方法。这个方法的主要作用就是把一些属性组装成一个Transformation类。这个方法会被父类的getTransformation方法调用。
再来看看一些类的使用。
2. initialize方法
public void initialize(int width, int height, int parentWidth, int parentHeight)
初始化工作,动画开始前的一些准备工作。
3. Interpolator方法
public void setInterpolator(Interpolator i)
定义动画执行过程一些加速度减速度,为了我们后面Transformation来服务的。
4. Transformation类
Transformation记录了仿射矩阵Matrix,动画每触发一次,会对原来的矩阵做一次运算,View的Bitmap与这个矩阵相乘就可以实现相应的操作(旋转、平移、缩放等)。
Transformation类封装了矩阵和alpha值,它有两个重要的成员,一是mMatrix,二是mAlpha(控制透明度)。
5.View中实现动画的过程
图形变换通过矩阵实现。图形变换是图形学中基本知识。简单来说就是,每种变换都是一次矩阵运算。在Android中,Canvas类包含当前矩阵,当前调用Canvas.drawBitmap(bm,x,y,Paint)绘制时,android会先把bmp做一次矩阵运算,然后将运算结果显示在Canvas上。这样编程人员只需不断修改Canvas的矩阵并刷新屏幕,View里对象就会不停的做图形变换,动画就形成了。
View创建动画对象,设置动画属性,调用invalidate刷新屏幕,启动动画;
invalidate方法触发了onDraw函数;在onDraw函数中,调用动画的getTransformation方法,得到当前时间点的矩阵将该矩阵设置成Canvas的当前矩阵调用canvas的drawBitmap方法,绘制屏幕。判断getTransformation的返回值,若为真,调用invalidate方法,刷新屏幕进入下一帧;若为假,说明动画完成。
6、setRepeatCount(int repeatCount)
//设置重复次数,INFINITE为无限 。
animation .setRepeatMode(Animation.RESTART);
7、setRepeatMode(int repeatMode)
////设置重复模式,RESTART为结束后重新开始,REVERSE为按原来的轨迹逆向返回
animation.setRepeatMode(Animation.RESTART);animation.setRepeatMode(Animation.REVERSE);
8、setAnimationListener(Animation.AnimationListener listener)
animation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { //动画开始处理 } @Override public void onAnimationEnd(Animation animation) { //动画结束处理 } @Override public void onAnimationRepeat(Animation animation) { //动画重新开始的时候处理 } });
9、setInterpolator(Interpolator i)
switch (position) { case 0: //加速进入 animation.setInterpolator(AnimationUtils.loadInterpolator(this, android.R.anim.accelerate_interpolator)); break; case 1: //减速进入 animation.setInterpolator(AnimationUtils.loadInterpolator(this, android.R.anim.decelerate_interpolator)); break; case 2: //加速进入.与第一个的区别为当repeatMode为reverse时,仍为加速返回原点 animation.setInterpolator(AnimationUtils.loadInterpolator(this, android.R.anim.accelerate_decelerate_interpolator)); break; case 3: //先往后退一点再加速前进 animation.setInterpolator(AnimationUtils.loadInterpolator(this, android.R.anim.anticipate_interpolator)); break; case 4: //减速前进,冲过终点前再后退 animation.setInterpolator(AnimationUtils.loadInterpolator(this, android.R.anim.overshoot_interpolator)); break; case 5: //case 3,4的结合体 animation.setInterpolator(AnimationUtils.loadInterpolator(this, android.R.anim.anticipate_overshoot_interpolator)); break; case 6: //停止前来回振几下 animation.setInterpolator(AnimationUtils.loadInterpolator(this, android.R.anim.bounce_interpolator)); break; }
看完这些方法,我们再来看看Animation的子类吧!
Android包含三种动画: Drawable Animation、View Animation、Property Animation(Android3.0新引入,Android官网推荐使用Property Animation)。
Drawable Animation:
Drawable Animation是逐帧动画,在代码中定义动画帧,使用AnimationDrawable类;XML文件能更简单的组成动画帧,在res/drawable文件夹,使用采用来定义不同的帧。
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true"> <item android:drawable="@drawable/frame_1" android:duration="200" /> <item android:drawable="@drawable/frame_2" android:duration="200" /> <item android:drawable="@drawable/frame_3" android:duration="200" /> <item android:drawable="@drawable/frame_4" android:duration="200" /> </animation-list>
其中android:oneshot=“true”表示该动画只播放一次,等于false时则循环播放。标签定义各个帧显示的图片。显示顺序依照定义顺序。
我们还有一种定义方法就是使用layer-list标签。
<?xml version="1.0" encoding="UTF-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:duration="100"> <layer-list> <item android:drawable="@drawable/login_loading_00" /> <item android:drawable="@drawable/login_loading_10" /> </layer-list> </item> <item android:duration="100"> <layer-list> <item android:drawable="@drawable/login_loading_01" /> <item android:drawable="@drawable/login_loading_11" /> </layer-list> </item> </animation-list>
以上xml文件与前面一个xml文件不大同,多了一个标签,该标签用法很简单,内包含的图片将层叠起来,在同一帧中一起显示。然后调用view的setBackgroundResource(动画资源)这样就行了。得到动画资源通过(AnimationDrawable) loadingImg.getBackground();
View Animation :(Tweened Animation)
View Animation分为4大类:AlphaAnimation,RotateAnimation,ScaleAnimation,
TranslateAnimation,分别对应透明度,旋转,大小,位移四种变化。
基于View的渐变动画,她只改变了View的绘制效果,而实际属性值未变。比如动画移动一个按钮位置,但按钮点击的实际位置仍未改变。View Animation的效果由四个因素决定:1)初始状态;2)结束状态;3)持续时间;4)Interpolator。
例如:
TranslateAnimation tAnim = new TranslateAnimation(0, 400, 0, 0); tAnim.setDuration(2000); view.startAnimation(tAnim); //横向位移400个单位
但是他并未改变view的属性,下面我们就来改变它的属性:
tAnim.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub LayoutParams params = view.getLayoutParams; params.leftMargin = 400; view.setLayoutParams(params); view.clearAnimation(); } }); break; } return true; } });
这样我们就使view真正的往右移动了400单位
Property Animation:
上面view Animation我们发现它并不能真正改变view的属性,下面我们就来看看能改变它属性的Property Animation属性。动画的对象除了传统的View对象,还可以是Object对象,动画之后,Object对象的属性值被实实在在的改变了。Property animation能够通过改变View对象的实际属性来实现View动画。任何时候View属性的改变,View能自动调用invalidate()来刷新。
我们先来看看通过ObjectAnimator实现一张icon由透明到不透明
//11以下的SDK ,导入nineoldandroids动画库ObjectAnimator.ofFloat(v, "alpha", 0.0f,1.0f) .setDuration(100) .start();
就是这样,是不是很简单,对于ObjectAnimator 提供了ofInt、ofFloat、ofObject,ofPropertyValuesHolder,这几个方法都是设置动画作用的元素、作用的属性、动画开始、结束、以及中间的任意个属性值。
1、例如:
ObjectAnimator.ofFloat(target, propertyName, values)
target :指的就是我们需要改变属性的view,
propertyName:我们可以任意命名,它的作用是getPropName通过propertyName反射获取后面设置的values值,
values:这个值我们可以设置一个values,也可以设置多个,只设置一个的时候,会认为当然对象该属性的值为开始(getPropName反射获取),然后设置的值为终点。如果设置两个,则一个为开始、一个为结束动画更新的过程中,会不断调用setPropName更新元素的属性,所有使用ObjectAnimator更新某个属性,必须得有getter(设置一个属性值的时候)和setter方法。
2、如果我们调用view对象的属性方法没有调用view的重绘,我们就需要自己调用通过:
anim.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { // view.postInvalidate(); // view.invalidate(); } });
来调用。
比如当我们既要透明由不透明到透明。然后慢慢的变小,我们就可以这样实现。
ObjectAnimator anim = ObjectAnimator.ofFloat(v, "alpha", 1.0f,0.0f).setDuration(1000);anim.start();anim.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float cVal = (Float) animation.getAnimatedValue(); Log.d("zgx", "cVal==========="+cVal); v.setAlpha(cVal); v.setScaleX(cVal); v.setScaleY(cVal); } });
3、我们再来看看ofPropertyValuesHolder的使用:
public void propertyValuesHolder(View view) { PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f); PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f); ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY,pvhZ).setDuration(1000).start(); }
就这样就可以实现上面例子的效果。
最后再来说说anim的监听动画开始,结束,被取消,重复等事件的addListener方法
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", 0.5f); anim.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator animation) { Log.e(TAG, "onAnimationStart"); } @Override public void onAnimationRepeat(Animator animation) { // TODO Auto-generated method stub Log.e(TAG, "onAnimationRepeat"); } @Override public void onAnimationEnd(Animator animation) { Log.e(TAG, "onAnimationEnd"); ViewGroup parent = (ViewGroup) mBlueBall.getParent(); if (parent != null) parent.removeView(mBlueBall); } @Override public void onAnimationCancel(Animator animation) { // TODO Auto-generated method stub Log.e(TAG, "onAnimationCancel"); } }); anim.start();
有时候会觉得,我只要知道结束就行了,上面的代码有点长,那就使用AnimatorListenerAdapter
anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { Log.e(TAG, "onAnimationEnd"); ViewGroup parent = (ViewGroup) mBlueBall.getParent(); if (parent != null) parent.removeView(mBlueBall); } });
Animation更详细内容参考,参考博客
更多相关文章
- ListView的一些属性设置
- (收集)ListView中常用属性
- [Android] Android Tweened Animations动画使用详解二
- Android控件属性大全[整理]
- 动画学习笔记-Android Animation
- Android编程示例之——横竖屏切换动画
- Android 同时播放缩放动画和位移动画 时, 位移的路径会发生偏移.
- [置顶] Android ViewPager+Fragment超高仿微信主界面(带底部图标