本篇讲android 3.0之前被广泛的动画框架——ViewAnimation。

目录

我将分为六部分来讲:

  • 概述
  • Alpha透明动画
  • Rotate旋转动画
  • Translate位移动画
  • Scale放缩动画
  • 最佳实践:带动画SplashScreen的实现
  • 简单总结

第一部分讲讲视图动画的特点,接着的四部分讲具体的视图动画类型,再接着的一部分通过一个例子来说明视图动画的运用,最后简单总结一下。

一、概述

其实叫“概述”有点名不符实,我只是想讲讲视图动画的特点,简单的扯两句实现原理,如何运用。除此再无其他!(友情提醒:可以只看加粗部分)

1.视图动画实现原理: 用一句话说明就是android通过矩阵运算来实现视图动画。 包含动画的View的ViewGroup在调用drawChild时会获取到动画的Tansformation值,然后调用canvas.concat(tansformationToApply.getMatrix()),进而矩阵运算等到动画效果。 大概过程就是在规定的时间里不断的进行矩阵计算,然后invalidate()。

2.ViewAnimation的最大特(缺)点: 动画过程对View的交互不造成任何影响,这里所说的影响是做动画的View的事件触发区域不会随着动画而改变,会造成View已经不再原来的位置了,但该位置还能触发相应的动作。这点就很反人类了,所以要特别注意。如果要想事件区域也发生变化,那就考虑用属性动画吧!
3.属性动画集 有时单一的视图动画不能满足要求(实际上都不能满足),那就可以考虑用多个属性动画组成动画集,来完成想要的效果。这点会在最后一部分讲到。
4.项目源码:Github
5.(想起再补充吧! ㄟ( ▔, ▔ )ㄏ)

二、Alpha透明动画

关于什么是Alpha就不赘述了。简单说一下Alpha动画的效果,就是View从透明到不透明或者相反的过程。(无图言diao, (╯▽╰),请看下面的动画)

下面我们来说说如何实现gif中的效果,直接给出代码:

  1. /**
  2. * 触发Alpha(透明)动画
  3. */
  4. @OnClick(R.id.btn_alpha) void onAlphaClicked() {
  5. AlphaAnimation alpha = new AlphaAnimation(0, 1);
  6. alpha.setDuration(2000);
  7. mStage.startAnimation(alpha);
  8. }

上面代码创建了一个Alpha动画,设置的效果是从完全透明到完全不透明,整个动画持续2秒,并指定了由mStage(这个例子中是ImageView)来完成动画。

关于AlphaAnimation,它有两个构造方法:

  1. AlphaAnimation (Context context, AttributeSet attrs)
  2. AlphaAnimation (float fromAlpha, float toAlpha)

第一个是从xml加载动画设置,视图动画都有这个构造方法,关于这部分后面再慢慢写。
第二个构造方法接受两个单精度浮点,第一个指定起始的alpha值,第二个终止的alph值。整个动画就是从起始alpha值到终止alpha值的变化过程。 
关于动画的其他设置: 视图动画族都是继承自 android.view.animation.Animation,其中抽象父类Animation定义了动画的全部操作集。每个子类基本没有新增方法,所以一切就变得简单了。(妈妈在也不用担心我记那么多api了 o(*≧▽≦)ツ)
developer文档:Animation操作集
常用设置:

  • getDuration() 返回动画持续时间
  • cancel() 取消一个动画
  • hasEnded() 判断动画是否结束
  • hasStarted() 判断动画是否开始
  • initialize(int width, int height, int parentWidth, int parentHeight) 同指定的尺寸去初始化动画的View和其ViewGroup,这个方法在四种视图动画中都有重写版本。
  • setRepeatMode(int repeatMode) 设置动画结束后是否重复
  • setStartTime(long startTimeMillis) 多少时间后启动动画
  • reset() 重置动画
  • ...

这部分其实是视图动画的公共部分,其他类型的视图动画也一样。

三、Rotate旋转动画

旋转动画的效果是这样的:

代码还是很简单:

  1. /**
  2. * 触发Rotate(旋转动画)
  3. */
  4. @OnClick(R.id.btn_rotate) void onRotateClicked() {
  5. RotateAnimation rotate = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f,
  6. Animation.RELATIVE_TO_SELF, 0.5f);
  7. rotate.setDuration(2000);
  8. mStage.startAnimation(rotate);
  9. }

相比于alpha动画,rotate旋转动画的构造就显得复杂多了,下面给出它的构造方法集:

  1. RotateAnimation(Context context, AttributeSet attrs)
  2.  
  3. RotateAnimation(float fromDegrees, float toDegrees)
  4.  
  5. RotateAnimation(float fromDegrees, float toDegrees, float pivotX,float pivotY)
  6.  
  7. RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)

在讲各个构造方法的区别前,先讲讲旋转操作需要具备什么条件才能进行。

  • 角度
    从哪个角度开始,到哪个角度结束,所以角度是必备条件。
  • 旋转中心
    旋转在成的效果是View按照某个定点旋转一定角度。

所以旋转动画的参数起始就是为了指定这两个条件。

  • RotateAnimation(Context context, AttributeSet attrs)
    第一个构造方法不多说了,它从xml加载旋转动画,所有需要的值都在xml定义好了的。
  • RotateAnimation(float fromDegrees, float toDegrees)
    起始角度和终止角度有两个参数决定,那定点呢?默认定点为View的起始点(0,0)也就是左上角。
  • RotateAnimation(float fromDegrees, float toDegrees, float pivotX,float pivotY)
    在第二个构造方法的基础上加入了对旋转中心坐标的指定。
  • RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
    这才是要讲的重点,(什么鬼!多出来的2个参数是什么? (ノಠ益ಠ)ノ彡┻━┻,不急不急,摆好 ┬—┬ノ('-'ノ),听我慢慢说),多出来的两个参数大大减少了我们的计算。它们是一组标志,取值为:ABSOLUTE、RELATIVE_TO_PARENT、RELATIVE_TO_SELF中的一个,分别表示指定的坐标是绝对坐标,相对于父控件坐标,相对于自己的坐标。怎么理解呢?绝对值就是你写多少就是多少,类似于方法二中的坐标。相对于父控件就是指定的值乘以父控件的对于值(宽、高)得到的坐标。相对于自己同理,只是变成乘以自己的宽高了。比如上面我写的例子里就是值自己的几何中心为旋转中心。(是不是减少了好多计算?! (^-^)V)

关于旋转动画,还想说明的是旋转的方向问题:

  • 当fromDegrees > toDegrees 旋转方向为顺时针
  • 当fromDegrees < toDegrees 旋转方向为逆时针

其他设置同上面alpha中讲的一样。

四、Translate位移动画

位移动画的效果如下:

代码实现:

  1. /**
  2. * 触发Translate(位移)动画
  3. */
  4. @OnClick(R.id.btn_translate) void onTranslateClicked() {
  5. TranslateAnimation translate = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f,
  6. Animation.RELATIVE_TO_SELF, 1f, Animation.RELATIVE_TO_SELF, 0f,
  7. Animation.RELATIVE_TO_SELF, 1f);
  8. translate.setDuration(2000);
  9. mStage.startAnimation(translate);
  10. }

位移动画的构造方法如下:

  1. TranslateAnimation(Context context, AttributeSet attrs)
  2.  
  3. TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta
  4.  
  5. TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)

同样的,我们先讨论位移动画需要哪些条件:

  • 起点
  • 终点

因为位移就是做直线运动,有起点终点就行了。 那么构造函数参数的意义就很明显了,就不叨叨了。

五、Scale缩放动画

缩放动画要达到以下效果: 
缩放动画的实现代码如下:

  1. /**
  2. * 触发Scale(缩放)动画
  3. */
  4. @OnClick(R.id.btn_scale) void onScaleClicked(){
  5. ScaleAnimation scale = new ScaleAnimation(0,1,0,1,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
  6. scale.setDuration(2000);
  7. mStage.startAnimation(scale);
  8. }

还是一样讲构造函数:

  1. ScaleAnimation(Context context, AttributeSet attrs)
  2.  
  3. ScaleAnimation(float fromX, float toX, float fromY, float toY)
  4.  
  5. ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY)
  6.  
  7. ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)

放缩是一个比例变换的过程,构建一个放缩动画第一项需要指定放缩比例,所以fromX、toX、fromY、toY就是用来指定放缩的比例的。比如:

fromX = 0f; toX=1f; fromY=0f; toY=1f;

就是上面gif中的效果,从无都原大小的动画。 缩放动画第二个需要指定的就是缩放中心,默认缩放中心为(0,0)。上面的gif指定的放缩中心为View的几何中心。下面来看几个不是几何中心的例子:

  • 默认旋转中心(0,0):ScaleAnimation(0,1,0,1)
  • 指定旋转中心(500,0):TranslateAnimation(0,1,0,1,500,0)

其它设置同上。

六、最佳实践:带动画SplashScreen的实现

扯了这么多基础,下面我用一个例子来串起来之前的所以内容。我将用ViewAnimation实现一个应用启动屏(SplashScreen),类似与知乎日报的SplashScreen,它能逐渐放大和变淡。
1.什么是SplashScreen?为什么要有SplashScreen? SplashScreen是全屏(一般是这样的)的用来在应用启动时展示的信息。比如QQ、微博、微信都有自己的SplashScreen。微信启动时那张蓝色地球图就是一个SplashScreen。
SplashScreen存在的原因我认为有(不一定正确):

  • 加载全局设置
  • 展示重要信息,诱导用户点击
  • 高(zhuang)大(bi)上( (⊙﹏⊙)b)

在SplashScreen展示期间可以进行应用设置的加载,必要的网络数据请求等,这些操作比较费时,但有时应用启动的关键,不能让用户傻傻的看着你加载时期白屏,所以弄个SplashScreen出来转移用户注意力。达到更好的体验效果。
2.SplashScreen实现原理
SplashScreen有两种常见的实现方式:

  • 使用一个view实现,然后在显示完成后gone掉。
  • 使用独立的Activity来实现,然后在显示完成后启动别的activity,并finish掉SplashActivity。

3.SplashScreen样例的实现 在这,我选用第二种实现方式,先来效果图:

这个Example中没有实际SplashScreenn期间干的事(加载设置之类的)我就是简单实现了效果。整个启动屏的效果就是先显示图片一秒钟,然后同时开始做alpha和scale动画,最后进入主界面。
1)布局:
布局很简单就是一个全屏的ImageView,就不多说了。
2)代码:

  1. @Override protected void onCreate(@Nullable Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. //设置全屏
  4. requestWindowFeature(Window.FEATURE_NO_TITLE);
  5. getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  6. WindowManager.LayoutParams.FLAG_FULLSCREEN);
  7.  
  8. setContentView(R.layout.activity_splash);
  9.  
  10. ActionBar actionBar = getSupportActionBar();
  11. if (actionBar != null) {
  12. actionBar.hide();
  13. }
  14.  
  15. ButterKnife.bind(this);
  16. mHandler = new Handler();
  17. //让图片显示一秒钟,然后开始动画
  18. mHandler.postDelayed(new Runnable() {
  19. @Override public void run() {
  20. //使用动画集,让多个动画同时启动
  21. AnimationSet animationSet = new AnimationSet(true);
  22. animationSet.setDuration(2000);
  23. AlphaAnimation alpha = new AlphaAnimation(1, 0);
  24. alpha.setDuration(2000);
  25. animationSet.addAnimation(alpha);
  26. ScaleAnimation scale = new ScaleAnimation(1, 2, 1, 2, Animation.RELATIVE_TO_SELF,
  27. 0.5f,
  28. Animation.RELATIVE_TO_SELF, 0.5f);
  29. scale.setDuration(2000);
  30. animationSet.addAnimation(scale);
  31. mSplash.startAnimation(animationSet);
  32. }
  33. }, 2000);
  34. //多少时间后启动主activity
  35. mHandler.postDelayed(new Runnable() {
  36. @Override public void run() {
  37. Intent intent = new Intent(SplashActivity.this, MainActivity.class);
  38. //在新的应用栈中启动activity
  39. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  40. startActivity(intent);
  41. //销毁这个开始屏幕,这个很重要不然按下返回键会回退到启动屏
  42. SplashActivity.this.finish();
  43. }
  44. }, 3800);
  45. }

关于上述代码,需要说明3点:

  • 全屏的设置除了设置窗口flag外,还需要讲actionbar给隐藏掉,设置窗口标志后只是没有了状态栏,但actionbar还在。
  • 第二个postDelayed方法的时间需要小于图片停留时间后动画时间的总和,不然会后短暂的图片还原状态。这很好理解,代码执行时需要时间的,并不能不保证直接就触发finish操作。
  • intent设置一个为FLAG_ACTIVITY_NEW_TASK的flag会使得新启动的activity在一个新的应用栈中。

你可以在我的Github里找到本篇的全部例子代码。

七、简单总结

至此全部关于ViewAnimation的内容算是讲完了,视图动画很简单,它只是作用于View的外观,并不会改变view的属性,也不会改变交互,这点需要特别注意。有序的组合各种视图动画也是能完成大部分的动画需求的,需要的解决动画间的配合。

tips:个人学习心得,可能有偏颇之处,如有错误,欢迎提交issue或指出!谢谢!

Android 动画基础——视图动画(View Animation)的更多相关文章

  1. Android动画主要包含补间动画(Tween)View Animation、帧动画(Frame)Drawable Animation、以及属性动画Property Animation

    程序运行效果图: Android动画主要包含补间动画(Tween)View Animation.帧动画(Frame)Drawable Animation.以及属性动画Property Animatio ...

  2. Android动画基础——属性动画(Property Animation)

    本篇涉及例子下载:Github 本篇讲android 3.0引入的属性动画框架,上篇写视图动画View Animation时就说过ViewAnimation的缺点,那就是动画作用的是view本身的视觉 ...

  3. Android动画(一)-视图动画与帧动画

    项目中好久没用过动画了,所以关于动画的知识都忘光了.知识总是不用则忘.正好最近的版本要添加比较炫酷的动画效果,所以也借着这个机会,写博客来整理和总结关于动画的一些知识.也方便自己今后的查阅. Andr ...

  4. Android动画之二:View Animation

    作为一个博客<Android其中的动画:Drawable Animation>.android动画主要分为三大部分.上一篇博客已经解说Drawable Animation的使用方法,即逐帧 ...

  5. Android开发之视图动画基础

    Android的animation由四种类型组成 XML中  alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面转移旋转 ...

  6. Android动画(二)-属性动画

    我们在上一篇博客中,讨论了视图动画与帧动画.那么这节课则要讨论更复杂,更强大的Property animation(属性动画). 视图动画使用简单,但是功能也简单.(只有那四种功能).并且也不改变Vi ...

  7. 浅谈Android样式开发之View Animation (视图动画)

    引言 一个用户体验良好的App肯定少不了动画效果.Android为我们提供了2种动画框架,分别是视图动画(View Animation)和属性动画(Property Animation).视图动画比较 ...

  8. Android动画总结#补间动画(Tween Animation/View Animation) #帧动画(Frame Animation/Drawable Animation)#属性动画(PropertyAnimation)

    1.共有三种动画,英文名字多种叫法如下 第一种动画:补间动画(Tween Animation/View Animation) 四个:RotateAnimation旋转. AlphaAnimation透 ...

  9. android动画基础之Animation

    android 动画 摘要: 概述 最近总结一下Android的一些东西,毕竟基础不牢地动山摇.本篇主要涉及Animation,对Tween和Frame动画做些总结. Tween Tween动画即补间 ...

随机推荐

  1. 前端切图:一个好看的表格css样式

    <!DOCTYPE html><html>        <head>        <meta charset="UTF-8">  ...

  2. Codeforces Round #443 (Div. 2) C: Short Program - 位运算

    传送门 题目大意: 输入给出一串位运算,输出一个步数小于等于5的方案,正确即可,不唯一. 题目分析: 英文题的理解真的是各种误差,从头到尾都以为解是唯一的. 根据位运算的性质可以知道: 一连串的位运算 ...

  3. Linux修改windows中文本文件出现的^M

    换行符的Linux与windows文本文件是不一致的,需要通过 :%s/^M$//g 其中^M的输入使用ctrl+v+m 可以删除^M

  4. 快来看看Google出品的Protocol Buffer,别仅仅会用Json和XML了

    前言 习惯用 Json.XML 数据存储格式的你们,相信大多都没听过Protocol Buffer Protocol Buffer 事实上 是 Google出品的一种轻量 & 高效的结构化数据 ...

  5. svn创建版本库和删除版本库

    作者:朱金灿 来源:http://blog.csdn.net/clever101 svn创建版本库的做法:使用cd命令进入版本仓库的根目录,我的是E:\Repository,然后运行命令: svnad ...

  6. DevCloud项目管理与Leangoo使用对比

    DevCloud(华为软件开发云)是集华为研发实践.前沿研发理念.先进研发工具为一体的研发云平台,面向开发者提供端到端的研发工具服务.项目管理是DevCloud服务之一,致力于为敏捷开发团队提供简单高 ...

  7. FileReader的编码问题

    有一个UTF-8编码的文本文件,用FileReader读取到一个字符串,然后转换字符集:str=new String(str.getBytes(),"UTF-8");结果大部分中文 ...

  8. css3中的渐变小总结

      = 导航   顶部 线性渐变 径向渐变 透明度 边框 阴影   顶部 线性渐变 径向渐变 透明度 边框 阴影 系列教程 CSS3 Gradient分为linear-gradient(线性渐变)和r ...

  9. OpenCV dll 源码调试—附加到进程

    使用CMake可以生成OpenCV源码的解决方案,然后就可以对OpenCV函数进行修改,功能剪切等操作了,对这部分内容感兴趣的可以浏览一下上一篇文章:CMake生成OpenCV解决方案&&am ...

  10. Java实现查找二叉树&C++的做法

    写了个Java的查找二叉树,用递归做的,不用递归的还没弄出来.先贴一下.回头再研究. BTreeTest.java: public class BTreeTest{ class Node{ Node ...