Android的动画可以分为三种,View动画、帧动画、属性动画。View动画通过对场景里的对象不断做图像变化(平移、缩放、旋转、透明度)从而产生动画效果,它是一种渐进式动画,而且View动画支持自定义。帧动画可以理解为图片切换动画(如果图片过多,会导致OOM)。属性动画为API11的新特性,属性动画通过通过动态地改变对象的属性从而达到动画效果。

  • View动画

View动画的种类:View动画的四种变换效果对应着Animation的四个子类。TranslateAnimation,ScaleAnimation,RotateAnimation,AlphaAnimation。这四种动画可以通过XML来定义,也可以通过代码动态创建。对于View动画来说,建议XML来定义,这是因为XML格式的动画可读性好。

View动画的四种变换
名称 标签 子类 效果
平移动画 <translate> TranslateAnimation 移动View
缩放动画 <scale> ScaleAnimation 放大或缩小View
旋转动画 <rotate> RotateAnimation 旋转View
透明度动画 <alpha> AlphaAnimation 改变View的透明度
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"android:interpolator="@android:anim/accelerate_decelerate_interpolator"android:shareInterpolator="true"android:duration="1000"android:fillAfter="false"><alpha android:fromAlpha="float"android:toAlpha="float" /><scale android:fromXScale="float"android:toXScale="float"android:fromYScale="float"android:toYScale="float"android:pivotX="float"android:pivotY="float" /><translate android:fromXDelta="float"android:toXDelta="float"android:fromYDelta="float"android:toYDelta="float" /><rotate android:fromDegrees="float"android:toDegrees="float"android:pivotX="float"android:pivotY="float" />
</set>

View动画可以是单个动画,也可以是一系列动画组成。<set>表示动画集合,对应AnimationSet类。

android:interpolator:表示动画集合所使用的插值器,插值器影响动画的速度,比如非匀速动画就需要通过插值器来控制动画的播放速度。

android:shareInterpolator:表示集合中的动画是否共享同一个插值器。如果不指定插值器,那么子动画就需要单独指定所需要的插值器或者使用默认值。

AlphaAnimation anim = (AlphaAnimation) AnimationUtils.loadAnimation(this, R.anim.anim_test);
TextView tv = findViewById(R.id.tv);
tv.startAnimation(anim);

除了XML定义动画之外,还可以使用代码创建动画。

AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
alphaAnimation.setDuration(300);
TextView tv = findViewById(R.id.tv);
tv.startAnimation(alphaAnimation);

注意:通过Animation的setAnimationListener的方法可以给View动画添加过程监听。如适用于带动画的启动页,监听动画完成后进入MainActivity。

anim.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {}
});

自定义View动画:

自定义View动画是一件简单而复杂的事情。说简单是:因为派生一种新动画只需要集成Animation这个抽象类,然后重写它的initialize和applyTransformation方法。在initialize中进行初始化工作,在applyTransformation中进行相应的矩阵变换即可。很多时候需要Camera来简化矩阵变换过程。说复杂,是因为需要运用到矩阵变换的过程,使用到数学上的概念。之后再做相关的分析讲解。

  • 帧动画

帧动画顺序播放一组预先定义好的图片,类似电影播放。不同于View动画,系统提供另外一个类AnimationDrawable来使用帧动画。帧动画的使用比较简单,先使用XML来定义一个AnimationDrawable。在drawable目录下创建:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"android:oneshot="false"><item android:drawable="@drawable/img1" android:duration="500"/><item android:drawable="@drawable/img2" android:duration="500"/><item android:drawable="@drawable/img3" android:duration="500"/>
</animation-list>

将上述的Drawable作为View的背景并通过Drawable来播放动画。

TextView tv = findViewById(R.id.tv);
tv.startAnimation(alphaAnimation);
AnimationDrawable animationDrawable = (AnimationDrawable) tv.getBackground();
animationDrawable.start();

注意帧动画比较容易引起OOM,所以避免使用尺寸较大的图片。

  • View动画的特殊场景使用

在一些特殊场景下,如ViewGroup中控制子元素的出场效果,在Activity中实现不同Activity之间的切换效果。

LayoutAnimation作用于ViewGroup,作为ViewGroup指定一个动画,这样当它的子元素出场时都具有这样的效果。常见的ListView的Item的出场以一定的动画效果出现。

定义LayoutAnimation如下:

//res/anim/anim_layout.xml<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"android:delay="0.5"android:animationOrder="normal"android:animation="@anim/anim_item" />

delay表示子元素开始动画的时间延迟。比如说元素入场动画周期为300ms,那么0.5表示每个子元素都需要延迟150ms才能播放入场动画。第一个子元素延迟150ms开始播放入场动画,第二个子元素延迟300m开始播放入场,以此类推。

animationOrder:子元素动画顺序,normal, reverse和random。

android:animation: 为元素指定具体的入场动画。

为ViewGroup指定android:layoutAnimation属性,对于ListView而言,指定之后就是Item的出场动画了。除了XML中指定LayoutAnimation之外,还可以通过LayoutAnimationController来实现,具体如下:

ListView listView = findViewById(R.id.list_view);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
listView.setLayoutAnimation(controller);

Activity的切换效果:

Activity有默认的切换效果,但是这个效果是可以自定义的,主要用到overridePendingTransition(int enterAnim, int exitAnim)这个方法,这个必须在startActivity(intent)和finish()之后被调用才能生效,它的参数含义如下:

enterAnim - Activity被打开时,所需要的动画资源id

exitAnim - Activity被暂停时,所需要的动画资源id

当启动一个Activity时,可以按照如下方式为其添加自定义的切换效果:

Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_anim, R.anim.exitAnim);

当Activityt退出时,也可以为其指定自定义的切换效果:

@Override
public void finish() {super.finish();overridePendingTransition(R.anim.enter_anim, R.anim.exitAnim);
}

Fragment也可以添加切换效果,可以通过FragmentTransaction中的setCustomAnimations()方法来添加切换动画,这个切换动画需要时View动画。还有其他的方法为Activity和Fragment添加切换动画,但是需要考略兼容为题。

  • 属性动画

属性动画是API11新加入的特性,和View动画不同,它对作用的对象进行扩展,属性动画可以对任何对象做动画,甚至还可以没有对象。属性动画可以对任意对象的属性进行动画而不仅仅是View。属性动画中有ValueAnimator, ObjectAnimator和AnimatorSet等概念。为兼容之前的版本,采用nineoldandroids源动画库。

ObjectAnimator继承自ValueAnimator,AnimatorSet是动画集合。属性动画需要定义在res/animator/目录下。

  1. 改变一个对象myObject的translationY属性,让其沿着Y轴向上移动一段距离,在默认的时间完成。

    1. ObjectAnimator.ofFloat(tv, "translationY", -myObject.getHeight()).start();

  2. 改变一个对象背景色属性,典型的改变View背景,下面的动画可以让背景色在3s内实现从0xFFFF8080到0xFF8080FF的渐变,动画会无限循环而且会有反转的效果。
    1. ValueAnimator colorAnim = ObjectAnimator.ofInt(myObject, "backgroundColor", 0xFFFF8080, 0xFF8080FF);colorAnim.setDuration(3000);colorAnim.setEvaluator(new ArgbEvaluator());colorAnim.setRepeatCount(ValueAnimator.INFINITE);colorAnim.setRepeatMode(ValueAnimator.REVERSE);colorAnim.start();

  3. 动画集合,5秒内对View的旋转,平移,缩放和透明度都进行改变。
    1. AnimatorSet set = new AnimatorSet();
      set.playTogether(ObjectAnimator.ofFloat(view, "rotationX", 0, 360),ObjectAnimator.ofFloat(view, "rotationY", 0, 180),ObjectAnimator.ofFloat(view, "rotation", 0, -90),ObjectAnimator.ofFloat(view, "translationX", 0, 100),ObjectAnimator.ofFloat(view, "translationY", 0, 100),ObjectAnimator.ofFloat(view, "scaleX", 1, 1.5f),ObjectAnimator.ofFloat(view, "scaleY", 1, 0.5f),ObjectAnimator.ofFloat(view, "alpha", 1, 0.5f, 1)
      );
      set.setDuration(5 * 1000).start();

属性动画除了代码实现之外,还可以通过XML来定义。

eg.

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><objectAnimator android:propertyName="x"android:duration="300"android:valueTo="300"android:valueType="intType" /><objectAnimator android:propertyName="y"android:duration="300"android:valueTo="300"android:valueType="intType"/>
</set>

加载上面的属性动画:

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.property_animator);
set.setTarget(view);
set.start();

建议:属性动画采用代码来实现,这是因为代码的方式会比较简单,更重要的是,在一个属性起始值无法确定的情况下,将无法将属性定义在xml文件中。

  • 插值器和估值器

 TimeInterpolater:时间插值器,它的作用是根据时间流逝的百分比来计算出当前属性改变的百分比,系统预置的有LinearInterpolator(线性插值器:匀速动画)、AccelerateDecelerateInterpolator(加速减速插值器:动画两头慢,中间快),DeceleratrInterpolator(减速插值器:动画越来越慢)等。

TypeEvaluator:类型估值算法,也叫做估值器。它的作用是根据当前属性改变的百分比来计算改变后的属性值,系统预置的有IntEvaluator(针对整型属性),FloatEvaluator(针对浮点型属性),ArgbEvaluator(针对Color属性)。

线性差值器,属于匀速动画,其源码为:

/*** An interpolator where the rate of change is constant*/
@HasNativeInterpolator
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {public LinearInterpolator() {}public LinearInterpolator(Context context, AttributeSet attrs) {}public float getInterpolation(float input) {return input; /** 输入值和返回值一样 */}/** @hide */@Overridepublic long createNativeInterpolator() {return NativeInterpolatorFactoryHelper.createLinearInterpolator();}
}

那到底输入数值是什么?这需要估值算法来确定,如整型估值器的源码为:

public class IntEvaluator implements TypeEvaluator<Integer> {/*** This function returns the result of linearly interpolating the start and end values, with* <code>fraction</code> representing the proportion between the start and end values. The* calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,* and <code>t</code> is <code>fraction</code>.** @param fraction   The fraction from the starting to the ending values* @param startValue The start value; should be of type <code>int</code> or*                   <code>Integer</code>* @param endValue   The end value; should be of type <code>int</code> or <code>Integer</code>* @return A linear interpolation between the start and end values, given the*         <code>fraction</code> parameter.*/public Integer evaluate(float fraction, Integer startValue, Integer endValue) {int startInt = startValue;return (int)(startInt + fraction * (endValue - startInt));}
}

evaluate方法的三个参数分别是估值小数,起始值,结束值。例子:匀速动画,对象从0位置到100,当估值小数位0.5的时候,根据算法result = 0 + 0.5(100 - 0) = 50。

属性动画要求对象有该属性的set方法和get方法(可选)。除了系统预置的插值器和估值算法外,我们还可以自定义。自定义差值算法需要实现Interpolator或TimeInterpolator;自定义估值算法需要实现TypeEvaluator。

属性动画的监听:

有两个常用的属性动画监听:AnimatorListener, AnimatorUpdateListener

ObjectAnimator animator = new ObjectAnimator();
animator.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}
});

从AnimatorListener的定义来看,它可以监听动画的开始,结束,取消和重复动画。

public static interface AnimatorUpdateListener {/*** <p>Notifies the occurrence of another frame of the animation.</p>** @param animation The animation which was repeated.*/void onAnimationUpdate(ValueAnimator animation);}

AnimatorUpdateListener比较特殊,它会监听整个动画过程,动画是由许多帧组成的,每播放一帧onAnimationUpdate()就会被调用一次,利用这个特征,我们可以做一些特殊事情。

  • 对任意属性做动画

例如TextView的宽度动画变为800的动画,当layout_width的属性为wrap_content时,是有动画的,但是如果设置为固定值之后,下面的属性动画就没有效果了。

//高度从原来的默认值变为800
ObjectAnimator objectAnimator = ObjectAnimator.ofInt(textView, "width", 800);
objectAnimator.setDuration(500);
objectAnimator.start();

这是因为:

public void setWidth(int pixels) {mMaxWidth = mMinWidth = pixels;mMaxWidthMode = mMinWidthMode = PIXELS;requestLayout();invalidate();
}

 public final int getWidth() {return mRight - mLeft;}

setWidth不是所谓意义上的宽度设置,所以就不会产生动画。对任意属性做动画,一般需要有set和get方法,设置流程如下:

如果没有属性设置获取权限,可以定义一个包裹类进行封装,实现set和get方法;如:

public static class ViewWrapper{private View mTarget;public ViewWrapper(View target){mTarget = target;}public void setWidth(int width){mTarget.getLayoutParams().width = width;mTarget.requestLayout();}public int getWidth(){return mTarget.getLayoutParams().width;}
}

ViewWrapper viewWrapper = new ViewWrapper(view);
ObjectAnimator widthAnimator = ObjectAnimator.ofInt(viewWrapper, "width", btn.getWidth(), 800).setDuration(500);
widthAnimator.start();

这样,上面的TextView就可以实现宽度的动画效果了。

自定义View设置相关属性,进行动画案例:

/*** 自定义圆环* 对属性progress设置set和get方法* 就可以对CircleProgress的progress进行属性动画*/
public class CircleProgress extends View{private Paint mPaint;private RectF rectF;private int progress = 270;int width, height;public CircleProgress(Context context) {super(context);init();}public CircleProgress(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init();}public CircleProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init(){mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeWidth(20);mPaint.setColor(Color.RED);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);if (widthMode == MeasureSpec.EXACTLY){width = widthSize;}else{width = 100; //设置为默认值
        }if (heightMode == MeasureSpec.EXACTLY){height = heightSize;}else{height = 100; //设置为默认值
        }rectF = new RectF(20, 20, width-20, height-20);setMeasuredDimension(Math.min(width, height), Math.min(width, height)); //矩形
    }@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawArc(rectF, -90, progress, false, mPaint);invalidate();}public void setProgress(int progress){this.progress = progress;}public int getProgress(){return progress;}
}

转载于:https://www.cnblogs.com/denluoyia/p/8978045.html

Android之动画相关推荐

  1. android 自定义loading,Android自定义动画-StarLoadingView

    今天来分享第二个自定义loading的动画,起了个名字叫 蹦跶的星星 ,还是老规矩先介绍,后上图. 实现效果在最后,GIF有点大,手机流量慎重. 介绍 首先声明做这个动画的初衷是为了学习和分享,所以从 ...

  2. android 三维动画效果,9款令人惊叹的HTML5 3D动画应用

    原标题:9款令人惊叹的HTML5 3D动画应用 之前我们已经向大家分享了很多HTML5动画应用了,大部分都非常炫酷,也有一小部分是很实用的.今天我们要向各位HTML5动画爱好者介绍更多的HTML5 3 ...

  3. 【学习笔记】Android视图动画学习

    2019独角兽企业重金招聘Python工程师标准>>> 1.Android View动画框架 Animation框架定义了透明度.旋转.缩放和位移几种常见的动画. 实现原理:每次绘制 ...

  4. android矢量动画 充电,android矢量动画

    android矢量动画! 直接来个例子就明白了!(这里我把与动画无关的属性都用-表示) 首先你要有个矢量图 比如这个矢量图xml文件叫"vector1",文件在res\drawab ...

  5. Android视图动画集合AndoridViewAnimations

    Android视图动画集合AndoridViewAnimations Android视图动画是针对视图对象的动画效果,包括对象平移.旋转.缩放和渐变四种类型.通过组合这四种类型,可以创建出无数种动画效 ...

  6. 使用android frame动画定义自己的ProgressBar

    使用android  frame动画定义自己的ProgressBar 在 res  /layout/ainm 目录下面建一个frame_ainm.xml文件 <?xml version=&quo ...

  7. android动画封装,Android属性动画封装,快速构建动画

    Android实现动画效果的方式主要有帧动画.补间动画.属性动画.关于安桌动画的基础知识可以查看这篇文章Android属性动画完全解析 这里我要讲的是如何快速构建出一个动画效果,如下图: 如果我们用属 ...

  8. Android m 自定义下拉菜单,Android实现动画效果的自定义下拉菜单功能

    我们在购物APP里面设置收货地址时,都会有让我们选择省份及城市的下拉菜单项.今天我将使用Android原生的 Spinner 控件来实现一个自定义的下拉菜单功能,并配上一个透明渐变动画效果. 要实现的 ...

  9. Android Activity动画属性简介

    Android Activity动画属性简介 在Android当中 设置activity的动画 需要复写 android:windowAnimationStyle这个属性 我们自定义一个动画样式来继承 ...

  10. Android 帧动画何时停止播放

    为什么80%的码农都做不了架构师?>>>    关于android帧动画没有提供结束播放的接口回调表示不理解,也许是基于播放动画的时候,系统在干其他事情,无法确切地保证动画在tota ...

最新文章

  1. JS验证框架的使用方法
  2. python能写软件吗-python代码能做成软件吗
  3. Apache Kylin Cube 的构建过程
  4. c#启动单个程序(互斥机制)
  5. cocos2d-x android 入门
  6. windows 安装yaml支持和pytest支持等
  7. java线程池 core_Java 线程池 ThreadPoolExecutor 的使用
  8. 习题:编写一个程序,请输入两个数字,并判断两个数字的大小。
  9. 电脑安装系统安装不上的几个问题(解决)
  10. origin游戏下载一直显示准备中的解决方法
  11. 加壳及脱壳《逆向工程》
  12. Vue创建项目的详细步骤
  13. Oracle12C-针对log4j漏洞补丁修复
  14. JGIT使用的常见问题
  15. Ribbon原理及使用详解
  16. Microsoft Visual C++ 14.0 is required.
  17. ps去水印通用方法和教程案例
  18. WebBrowser抓图示例——截取网页上的验证码图片
  19. NPN、PNP型三极管的常见问题
  20. 哈工大计算机学院学号,【复试机试内容回忆汇总帖】2019年哈尔滨工业大学计算机考研...

热门文章

  1. Struts2笔记——struts常用标签
  2. Mathematics for Computer Graphics
  3. OCS Inventory NG使用之在windows 2008 R2平台下安装服务器端(二)
  4. 最新17个紫色风格网页设计作品欣赏
  5. 如何提高数据库访问效率
  6. 滴眼液的ph值与胶原纤维的粘结性(还没写完)
  7. flink的savepoints和checkpoints以及state Query(暂时无法全部完成)
  8. kill不掉 spark-submit
  9. sublime+virtualenv+pyspark执行的时候报Unable to load native-hadoop library for your platform
  10. 基于水色图像的水质评价