Android APP完整基础教程(13)应用资源-动画
动画模式在android系统中被分为三类,分别为:
- tween(view) animation:补间动画
- frame(drawable) animation:逐帧动画
- property animation:属性动画
本章节分别对齐进行解读。
1 Tween Animation
1.1 Tween Animation基础
Animation是以XML格式定义的,XML文件存放在路径res/anim下。这里按照XML文档的结构{父节点|子节点|属性}来介绍Tween Animation。先介绍Tween Animation共同的节点属性,如下所示:
Tween Animation由4种基本动画组成:Alpha(渐变透明度)、Scale(缩放)、Translate(位置移动)、Rotate(旋转),同时Animation类还有AlphaAnimation、ScaleAnimation、 TranslateAnimation、RotateAnimation 4个子类与之分别对应,每个子类都在父类的基础上增加了各自独有的属性。分别解读如下:
@1 Alpha属性说明:
@2 Scale属性说明:
@3 Translate属性说明:
@4 Rotate属性说明:
1.2 Tween Animation的用法
Tween Animation的用法有2种:从XML文件中读取 和 代码中设置/读取。
@1 代码中直接从XML资源中读取Animation并使用
用XML定义的动画放在/res/anim/文件夹内,XML文件的根元素可以为<alpha>,<scale>,<translate>,<rotate>, interpolator元素 或<set>(表示以上几个动画的集合,set可以嵌套)。默认情况所有动画是同时进行的,可以通过startOffset属性设置各个动画的开始偏移(开始时间)来达到动画顺序播放的效果。定义好动画XML文件后通过代码对指定的View应用该动画。如下所示:
ImageView XXXImage = (ImageView)findViewById(R.id.spaceshipImage);
Animation yyyAnimation=AnimationUtils.loadAnimation(this,R.anim.yyy);
XXXImage.startAnimation(yyyAnimation);
@2 通过代码设置Tween Animation属性
代码中使用Animation子类来初始化Animation对象。Animation基类包含大量的set/getXXX()函数来设置/读取Animation的属性。相关方法可参照文档:Android Animation XML属性。
Tween Animation关于动画相关的方法可参照文档:Android Animation method解读。
1.3 动画的运行控制与模式
@1 Interpolator
动画的进度使用 Interpolator来控制,interpolator定义一个动画的变化率,用于在运行时控制动画。这使得基本的动画效果(alpha, scale, translate, rotate)得以加速,减速,重复等。Interpolator 是基类,封装了所有 Interpolator 的共同方法,它只有一个方法,即 getInterpolation (float input),该方法提供了几个Interpolator 子类,实现了不同的速度曲线,如下:
说明:对于 LinearInterpolator ,变化率是个常数,即f(x) = x。Interpolator其他的几个子类,也都是按照特定的算法,实现了对变化率。还可以定义自己的Interpolator子类,实现抛物线、自由落体等物理效果。
@2 动画运行模式
- 独占模式:程序主线程进入一个循环,根据动画指令不断刷新屏幕,直到动画结束。
- 中断模式:单独线程对时间计数,隔一段时间给主线程发通知,主线程接到通知后更新屏幕。
@3 动画实现原理
- Transformation记录了仿射矩阵Matrix,动画每触发一次,会对原来的矩阵做一次运算, View的Bitmap与这个矩阵相乘就可实现相应的操作(旋转、平移、缩放等)。
- 图形变换通过仿射矩阵实现。图形变换是图形学中的基本知识,简单来讲,每种变换都是一次矩阵运算。在 Android中,Canvas 类中包含当前矩阵,当调用Canvas.drawBitmap(bmp, x, y, Paint)绘制时,Android会先把bmp做一次矩阵运算,然后将运算的结果显示在Canvas上。之后只需不断修改Canvas的矩阵并刷新屏幕,View里的对象就会不停的做图形变换,因此就形成了动画。
2 Frame Animation
Android用AnimationDrawable类来定义和使用Frame Animation。它可以在XML Resource定义(还是存放到res/anim文件夹下),也可以使用AnimationDrawable中的API定义。与Tween Animation不同,Frame Animation是顺序播放事先做好的图像,通过一系列Drawable依次显示来模拟动画的效果。在XML中的定义方式如下:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"android:oneshot="true"><item android:drawable="@drawable/XXX1" android:duration="200" />...
</animation-list>
说明:必须以<animation-list>为根元素,以<item>表示要轮换显示的图片,duration属性表示各项显示的时间。XML文件要放在/res/drawable/
@2 Drawable Animation使用示例:
定义一帧一帧的动画item,配置如下所示:
<animation-list xmlns:android=”http://schemas.android.com/apk/res/android”
android:oneshot=”true”><item android:drawable=”@drawable/XXX1″ android:duration=”200″ /><item android:drawable=”@drawable/XXX2″ android:duration=”200″ /><item android:drawable=”@drawable/XXX3″ android:duration=”200″ />
</animation-list>
其包含3帧动画,3帧动画中分别应用了drawable中的3张图片:XXX1、XXX2、XXX3,每帧动画持续200毫秒。然后我们将以上XML保存在res/anim/文件夹下,命名为XXX.xml。
编写代码,显示动画的代码如下:
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);imageView = (ImageView) findViewById(R.id.imageView);imageView.setBackgroundResource(R.drawable.drawable_anim);anim = (AnimationDrawable) imageView.getBackground();
}public boolean onTouchEvent(MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_DOWN) {anim.stop();anim.start();return true;}return super.onTouchEvent(event);
}
注意:
- 调用Imageview的setBackgroundResource方法,如果直接在XML布局文件中设置其src属性,当触发动画时会ForceClose问题。
- 在start()前要先stop(),不然第一次动画运行后会停在最后一帧,这样动画就只会触发一次。
- 不要在onCreate中调用start,因为AnimationDrawable还没有完全跟Window相关联,如果想要界面显示时就开始动画的话,可以在onWindowFoucsChanged()中调用start()。
@3 阅读Android 文档中对AnimationDrawable的介绍,关键内容整理如下:
更多关于AnimationDrawable的介绍,查看文档:Android AnimationDrawable详细解读
注意:Frame Animation 的XML 文件中不定义 interpolator 属性,因为定义它没有任何意义。
3 Animator
Animator代表一个属性动画,但是它只是一个抽象类。我们通常会使用它的子类:AnimatiorSet、ValueAnimator、ObjectAnimator、TimeAnimator。XML文件应放在res/animator/中。
3.1 属性动画的工作方式
@1 属性动画,它更改对象的实际属性。
在Tween Animation中,其改变的是View的绘制效果,View的属性保持不变,比如无论你在对话中如何缩放Button的大小,Button有效点击区域还是没有应用动画时的区域,其位置与大小都不变。在属性动画中,改变的是对象的实际属性,如Button的缩放,Button的位置与大小属性值都改变了。且属性动画不止可以应用于View,还可以应用于任何对象。属性动画只是表示一个值在一段时间内的改变,当值改变时要做什么事情由我们来决定。
@2 在Property Animation中,可以对动画应用以下属性:
3.2 常见属性动画解读&代码使用实例
3.2.1 ValueAnimator动画(代码实现机制)
整个属性动画机制当中最核心的一个类,属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等,是一个非常重要的类。但是ValueAnimator的用法却一点都不复杂,实例(将一个值从0平滑过渡到1,时长300毫秒,就可以这样写)如下:
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
anim.setDuration(300);
anim.start();
3.2.2 ObjectAnimator动画(代码实现机制)
相比于ValueAnimator,ObjectAnimator更常用,ValueAnimator不过是对值进行了平滑的动画过渡。而ObjectAnimator(继承自ValueAnimator)可以直接对任意对象的任意属性进行动画操作。
@1 alpha案例
一个TextView在5秒中内从常规变换成全透明,再从全透明变换成常规,代码如下:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
animator.setDuration(5000);
animator.start();
@2 rotation案例
将TextView进行一次360度的旋转,将@1中第二个参数改成"rotation",然后将动画的初始值和结束值分别设置成0和360,代码如下:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
animator.setDuration(5000);
animator.start();
@3 translation案例
将TextView先向左移出屏幕,然后再移动回来,代码如下:
float curTranslationX = textview.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "translationX",curTranslationX, -500f, curTranslationX);
animator.setDuration(5000);
animator.start();
先是调用了TextView的getTranslationX()方法来获取到当前TextView的translationX的位置,然后ofFloat()方法的第二个参数传入"translationX",后面三个参数用于告诉TextView如何移动。
@4 Scale实例
将TextView在垂直方向上放大3倍再还原,将ofFloat()方法的第二个参数改成了"scaleY",表示在垂直方向上进行缩放,代码如下:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "scaleY", 1f, 3f, 1f);
animator.setDuration(5000);
animator.start();
@5 特殊说明
关于 ofFloat()方法的第二个参数传递参数:不局限于alpha、rotation、translationX和scaleY这些值,我们可以传入任意值到ofFloat()方法的第2个参数。因为ObjectAnimator在设计的时候就没有针对于View来进行设计,而是针对于任意对象的,它所负责的工作就是不断地向某个对象中的某个属性进行赋值,然后对象根据属性值的改变再来决定如何展现出来。
3.2.3 组合动画
@1 基本概念
独立动画实现的视觉效果有限,因此将多个动画组合到一起播放就显得尤为重要。实现组合动画主要借助AnimatorSet这个类,这个类提供了一个play()方法,传入Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder实例,AnimatorSet.Builder中包括以下四个方法:
after(Animator anim) //将现有动画插入到传入的动画之后执行。
after(long delay) //将现有动画延迟指定毫秒后执行。
before(Animator anim) //将现有动画插入到传入的动画之前执行。
with(Animator anim) //将现有动画和传入的动画同时执行。
有这四个方法,我们就可以完成组合动画的逻辑。
@2 使用实例
这里让TextView先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作,关键代码如下所示:
ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f);
ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
AnimatorSet animSet = new AnimatorSet();
animSet.play(rotate).with(fadeInOut).after(moveIn);
animSet.setDuration(5000);
animSet.start();
先创建三个动画对象,然后new出一个AnimatorSet对象后将这三个动画对象进行播放排序,让旋转和淡入淡出动画同时进行,并把它们插入到了平移动画的后面,最后设置动画时长及启动动画。
3.3 属性动画XML使用实例
3.3.1 ValueAnimator动画使用实例
ValueAnimator代码和xml设置中,因为不是操作对象,所以没有setPropertyName,只是根据value进行某种动作需要加监听器,监听值的变化做相应的处理。xm配置如下:
<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator" android:duration="10000" android:startOffset="1000" android:repeatCount="infinite" android:repeatMode="restart" android:valueFrom="1" android:valueTo="100" android:valueType="intType">
</animator>
加载XML动画,关键代码实现如下:
ValueAnimator valueAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator);
valueAnimator.setTarget(tv_num);
valueAnimator.setEvaluator(new TypeEvaluator<Integer>() { @Override public Integer evaluate(float fraction, Integer startValue, Integer endValue) { System.out.println("时间比率,fraction:" + fraction); System.out.println("结果值:" + (int)((startValue + fraction * (endValue - startValue)) / 10 * 10)); return (int)((startValue + fraction * (endValue - startValue)) / 10 * 10); }
});
valueAnimator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //在onAnimationUpdate中 该值返回第一个动画的 当前帧的evaluate 值 System.out.println("animation.getAnimatedValue()==" + animation.getAnimatedValue()); tv_num.setText(animation.getAnimatedValue() + ""); }
});
valueAnimator.start();
3.3.2 ObjectAnimator动画XML的使用实例
动画XML定义如下:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:propertyName="scaleX" android:repeatCount="1" android:repeatMode="reverse" android:valueFrom="1.0" android:valueTo="2.0" >
</objectAnimator>
加载XML动画,关键代码如下所示:
imageview_scale.setBackground(getResources().getDrawable(R.drawable.a11));
ObjectAnimator scaleAnimator = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.scale_object_animator);
scaleAnimator.setTarget(imageview_scale);//设置动画作用的目标对象
scaleAnimator.setDuration(1000);
scaleAnimator.setRepeatCount(50);
scaleAnimator.start();
3.3.3 AnimatorSet 动画集
由ObjectAnimator 和 ValueAnimator 组成,对应的xml中的写法类似为
<set> <objectAnimator /> ... <animator />... </set>
xml定义动画集一般在文件夹res/animator下,这里是res/animator/set_rotate_scale.xml
@1 XML配置文件定义如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together"><!-- android:ordering together表示同时运行动画, sequentially 表示按顺序执行以下动画 --> <set> <objectAnimator android:propertyName="rotationX" android:repeatCount="50" android:repeatMode="reverse" android:valueFrom="0" android:valueTo="20" /> <objectAnimator android:propertyName="rotationY" android:repeatCount="50" android:repeatMode="reverse" android:valueFrom="0" android:valueTo="45" android:valueType="floatType" /> </set> <set> <objectAnimator android:propertyName="scaleX" android:repeatCount="50" android:repeatMode="reverse" android:valueFrom="1.0" android:valueTo="2.0" > </objectAnimator> <objectAnimator android:propertyName="scaleY" android:repeatCount="50" android:repeatMode="reverse" android:valueFrom="1.0" android:valueTo="2.0" > </objectAnimator> </set>
</set>
加载XML动画集,代码实现如下:
imageview_rotate.setBackground(getResources().getDrawable(R.drawable.a11));
AnimatorSet animatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.set_rotate_scale);
animatorSet.setTarget(imageview_rotate);
animatorSet.setDuration(1000);
animatorSet.setInterpolator(new BounceInterpolator());//设置end时的弹跳插入器
animatorSet.start();
更多关于动画的内容可查看文档:Android 动画解读
4 Animator监听器
若我们希望监听到动画事件,动画何时开始,何时结束,然后在开始或者结束的时候去执行一些逻辑处理。这个功能是完全可以实现的,Animator类当中提供了一个addListener()方法,这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。
只要是继承自Animator的,addListener()这个方法算是个通用的方法,添加一个监听器的代码如下所示:
anim.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator animation) {/*动画开始时*/} @Override public void onAnimationRepeat(Animator animation) {/*动画重复时*/} @Override public void onAnimationEnd(Animator animation) {/*动画结束时*/} @Override public void onAnimationCancel(Animator animation) {/*动画取消时*/}
});
但是也许很多时候我只想要监听动画响应的单一事件,那么可以使用AnimatorListenerAdapter,使用这个类就可以解决掉实现接口繁琐的问题了,如下所示:
anim.addListener(new AnimatorListenerAdapter() {});
这里我们向addListener()方法中传入这个适配器对象,由于AnimatorListenerAdapter中已经将每个接口都实现好了,所以这里不用实现任何一个方法也不会报错。那么如果想监听动画结束这个事件,就只需要单独重写这一个方法就可以了,如下所示:
anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { }
});
Android APP完整基础教程(13)应用资源-动画相关推荐
- Android APP完整基础教程(17)图形系统-SurfaceView
1 SurfaceView的绘图机制 @1 理解SurfaceView 为什么要使用SurfaceView,而不是直接使用View? 这里要考虑到动态场景和静态场景的差异,相对于动态场景: View组 ...
- 2022 最新 Android 基础教程,从开发入门到项目实战【b站动脑学院】学习笔记——第二章:Android App 开发基础
第 2 章 Android App开发基础 本章介绍基于Android系统的App开发常识,包括以下几个方面:App开发与其他软件开发有什么不一 样,App工程是怎样的组织结构又是怎样配置的,App开 ...
- Android APP 快速开发教程(安卓)
Android APP 快速开发教程(安卓) 前言 本篇博客从开发的角度来介绍如何开发一个Android App,需要说明一点是,这里只是提供一个如何开发一个app的思路,并不会介绍很多技术上的细节, ...
- 《Android 移动应用基础教程(Android Studio)(第2版)》【课本客观题】+【学习通2023春】【参考答案】
文章目录 超星学习通智能终端软件开发(基于Android Studio环境)章节作业(39) 一 二 三 四 五 六 课本一 课本二 课本三 课本四 课本五 课本六(无) 课本七 课本八 课本九 课本 ...
- Android App开发基础
Android App开发基础 App的开发特点 (1)App的运行环境 1.使用数据线把手机连到电脑上 2.在电脑上安装手机的驱动程序 3.打开手机的开发者选项并启用USB调试 4.将连接的手机设为 ...
- 《Android移动应用基础教程》(Android Studio)(第二版)黑马程序员 课后习题答案
<Android移动应用基础教程>(Android Studio)(第二版)黑马程序员 课后习题答案 目录 第1章 Android基础入门 第2章 Android常见界面布局 第3章 An ...
- 傻瓜式Android APP开发入门教程
这篇文章主要介绍了Android APP开发入门教程,从SDK下载.开发环境搭建.代码编写.APP打包等步骤一一讲解,非常简明的一个Android APP开发入门教程,android各种机子和rom的 ...
- android移动应用基础教程--qq账号与密码
android移动应用基础教程--qq账号与密码 android移动应用基础教程p115案例 实战演练-保存QQ账号密码. activity_main.xml <?xml version=&qu ...
- 创建android程序时 默认使用布局是,《Android移动应用基础教程》中国铁道出版社课后习题(附答案)...
<Android移动应用基础教程>中国铁道出版社课后习题(附答案) 第2章Android UI开发 一.填空题 1.Android中的布局分为6种,分别是RelativeLayout.Li ...
最新文章
- 测试三相无刷电机驱动器 XXD2212 电调
- LINUX挂接移动硬盘
- 动态规划套路:最大子数组和
- R语言观察日志(part10)--file函数
- java课程设计 博客园_java课程设计
- 解析可变参数函数的实现原理(printf,scanf)
- 工作325:uni-日期小于10补0
- QML笔记-使用Row的时候要注意的地方(一定要指明高度和宽度)
- python元组和列表都支持的方法是_Python进阶1-元组和列表
- 江门计算机职称考试时间,江门职称计算机考试时间
- cmake构建NNIE工程
- linux 提取有效源码,MPSOC之4——petalinux提取源码
- ESP8266-01/01S配对阿里云生活物联网教程(超详细)
- 2021 泰迪杯 C 题
- 从零开始研发GPS接收机连载——1、想法的萌发
- 短视频制作难度大吗?怎么剪辑短视频?
- 《激荡三十年》十八、青春飞扬——互联网的崛起
- 计算机连接未识别的网络,电脑网络连接出现未识别的网络怎么办
- springboot网上电子书店下载购买系统-图书商城网站961h3-java-ssm二级分类
- (十九)jmeter3.0插件管理---学习笔记
热门文章
- 织梦 php MIP改造,织梦dedecms MIP改造图片img转img-mip处理方法
- k米魔云8服务器系统在哪购买,线上KTV“K米·魔云6”上市发布会在贵州举行
- 从技术到管理,数据人如何开展工作?
- 禁止输入空格键demo效果示例(整理)
- Fabric源码流程分析之Orderer篇
- Automatic Head and Neck Tumor Segmentation in PET/CT with Scale Attention Network(HECKTOR2020第四名)
- matlab中继电器叫什么,解析汽车继电器中继电器各脚的区别及接线
- RSA PKCS1和PKCS8的ASN格式
- 论文研究 | 机器视觉下的普通国省干线公路落物识别
- 微信小程序携带参数的页面跳转