android进阶4step1:Android动画处理与自定义View——动画基础1
文章内容
- 逐帧动画
- 视图动画系统
- 属性动画系统
-
动画的种类
分类转:https://blog.csdn.net/pzm1993/article/details/77167049
-
Android的动画可以分为以下3种:
- 图片动画
图片动画,其实也是逐帧动画,是通过一个接一个的加载绘制对象资源来创建动画,按顺序的播放,像一个胶卷。对于视图动画,他只是单独的图片内容在变换,而不是整个视图。很显然,如果图片过多多大就会导致OOM异常。
- View动画
视图动画,通多对整个视图不断做图像的变换(平移,缩放,旋转,透明度)产生的动画效果,是一种渐进式动画。
其中观看动画又可以分为:补间动画和逐动动画
- 属性动画
属性动画,在Android 3.0的(API级别11)引入的,该属性动画系统可以制作动画的任何对象的属性。但是一般来说,属性动画系统是首选的使用方法,因为它更灵活,并提供更多功能。
一,逐帧动画
由多个图像组成的自定义加载动画,每一张图片作为动画的一帧,当顺序执行并给它一定时间间隔展示就形成一种动画的效果
使用AnimationDrawable
定义转:https://www.jianshu.com/p/ce5014c4bc95
的动画一种方法Drawables的英文逐个加载一系列柯林斯绘制资源来创建³³动画。这是一个传统的动画,它是由一系列不同的图像创建的,按照顺序播放,就像一卷电影一样。本。AnimationDrawable类的英文柯林斯绘制动画的基础。
虽然您可以使用AnimationDrawable类API在代码中定义动画的框架,但使用列出组成动画的框架的单个XML文件更简单。这种动画的XML文件属于res/drawable/您的Android项目的目录。在这种情况下,指令的英文动画每帧的顺序状语从句:持续时间。
它的实际相当于装绘制的一种容器,来控制绘制的显示
具体使用:
1,我们准备了三张图片:frame1,2,3来当做这个动画的三帧

2,新建工程,在将图片放到drawable文件夹下,并在drawable文件下(右键new)创建一个drawable资源文件文件

3,(frameanimation.xml)XML由文件一个元素作为根节点状语从句:一系列子节点组成<animation-list><item>
- 每一个项目对应一帧
- 持续时间:该帧持续的时间
- 绘制:该帧对应的图片
4,创建视图展示动画activity_main.xml
5.FrameAnimationActivity.java实现动画效果
重要的三个属性:
- 开始(); 开启动画
- 停止();停止动画
- setOneShot(boolean b);让动画执行一次
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;public class FrameAnimationActivity extends AppCompatActivity {private View mAnimationView;private AnimationDrawable animationDrawable;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//初始化视图mAnimationView = findViewById(R.id.frame_animation);//拿到视图的背景,也就是之前定义的drawable 强转为AnimationDrawableanimationDrawable = (AnimationDrawable) mAnimationView.getBackground();}public void onClick(View view) {switch (view.getId()) {case R.id.btnStart:animationDrawable.start();break;case R.id.btnStop:animationDrawable.stop();break;case R.id.btnOneShot://默认每一帧都是无限循环的//可以通过这个属性设置只执行一轮animationDrawable.setOneShot(true);break;}}
}
效果:

二,视图动画系统(View animation)
视图动画的作用对象只能是查看,同在一个图形通过在界面上进行透明度,缩放,旋转,平移的变化。
查看动画的分类:
view动画支持4中动画效果,分别是:
- 透明度动画(AlphaAnimation)
- 缩放动画(ScaleAnimation)
- 平移动画(TranslateAnimation)
- 旋转动画(RotateAnimation)
- 集合动画(AnimationSet)
不同动画与Java类、xml文件关键字对应关系如下:转:https://www.jianshu.com/p/26a801a755a0
| 名称 | Java子类 | xml关键字 | 说明 |
|---|---|---|---|
| 透明度动画 | AlphaAnimation | 放置在res/anim/目录下 | 透明度渐变 |
| 旋转动画 | RotateAnimation | 放置在res/anim/目录下 | 视图旋转 |
| 缩放动画 | ScaleAnimation | 放置在res/anim/目录下 | 放大/缩小 视图尺寸大小 |
| 平移动画 | TranslateAnimation | 放置在res/anim/目录下 | 视图位置移动 |
| 复合动画 | AnimationSet | 放置在res/anim/目录下 | 一个持有其它动画元素alpha、scale、translate、rotate或者其它set元素的容器 |
如图所示,图中几个类多是Animation的子类,在java代码中具体实现也是通过这些子类来实现

由于Animation是抽象基类,其提供了一些通用的动画属性方法,如下所示
| xml属性 | Java方法 | 说明 |
|---|---|---|
| android:detachWallpaper | setDetachWallpaper(boolean) | 是否在壁纸上运行 |
| android:duration | setDuration(long) | 动画的运行时间(以毫秒为单位);必须设置 |
| android:fillAfter | setFillAfter(boolean) | 动画结束时是否保持动画最后的状态;默认为false,优先于fillBefore |
| android:fillBefore | setFillBefore(boolean) | 动画结束时是否还原到开始动画前的状态;默认为true |
| android:fillEnabled | setFillEnabled(boolean) | 是否应用fillBefore的值,对fillAfter无影响;默认为true |
| android:interpolator | setInterpolator(Interpolator) | 设定插值器(指定的动画效果,譬如回弹等) |
| android:repeatCount | setRepeatCount(int) | 重复次数 |
| android:repeatMode | setRepeatMode(int) | 重复类型有两个值,reverse表示倒序回放,restart表示从头播放 |
| android:startOffset | setStartOffset(long) | 调用start函数之后等待开始运行的时间,单位为毫秒 |
| android:zAdjustment | setZAdjustment(int) | 表示被设置动画的内容运行时在Z轴上的位置(top/bottom/normal),默认为normal |
这4种动画既能分开独立实现,也可以组合实现复合动画AnimationSet。如果这些动画还是满足不了你,可以自定义动画。不过,后面有了属性动画之后,大部分还是可以满足需求。
view动画的实现可以通过Xml来定义,也可以通过java代码来动态设置。对于view动画,建议使用XML来定义动画,可读性好,而且能过复用。而对于属性动画,则建议是通过代码动态设置,后文会介绍。
一、透明度动画(AlphaAnimation)
控制视图的透明度
透明度动画(Alpha)-- 属性
| xml属性 | Java方法 | 说明 |
|---|---|---|
| android:fromAlpha | AlphaAnimation(float fromAlpha, …) | 动画开始的透明度(0.0到1.0,0.0是全透明,1.0是不透明) |
| android:toAlpha | AlphaAnimation(…, float toAlpha) | 动画结束的透明度,同上 |
步骤:
1、在res目录下创建anim文件夹 新建一个xml文件 使用
2、创建显示动画的布局 这里以TextView为这个视图 这里是:viewanimation.xml
3.java代码实现 实现点击textView 透明度发生变化的效果
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;import com.demo.android4step1.R;/*** 文件描述:
*
作者:Mr-Donkey
*
创建时间:2018/12/9 16:40
*
更改时间:2018/12/9 16:40
*
版本号:1
*/
public class AlphaAnimationActivity extends AppCompatActivity {private Animation animation;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.viewanimation);}public void onClick(View view) {switch (view.getId()) {case R.id.tv_alpha://加载动画拿到 animation对象animation = AnimationUtils.loadAnimation(this, R.anim.alpha_animation);//通过此时的view设置动画view.startAnimation(animation);break;}}
}
效果:

二、缩放动画(ScaleAnimation)
控制每一个视图的X、Y轴的缩放程度
缩放动画(Scale)-- 属性
| xml属性 | Java方法 | 说明 |
|---|---|---|
| android:fromXScale | ScaleAnimation(float fromX, …) | 初始X轴缩放比例,1.0表示无变化 |
| android:toXScale | ScaleAnimation(…, float toX, …) | 结束X轴缩放比例 |
| android:fromYScale | ScaleAnimation(…, float fromY, …) | 初始Y轴缩放比例 |
| android:toYScale | ScaleAnimation(…, float toY, …) | 结束Y轴缩放比例 |
| android:pivotX | ScaleAnimation(…, float pivotX, …) | (基准点)缩放起点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角以父控件宽度的50%做为初始点) |
| android:pivotY | ScaleAnimation(…, float pivotY) | (基准点)缩放起点Y轴坐标,同上规律 |
实现步骤:
1、在上面anim文件夹中新建xml文件 使用
2、在上面的布局viewanimation.xml中
将textView的部分属性抽取出来(如果有多个view共用的话,抽取style)
进入布局文件 点击Refactor——>Extract——>Style

提取共用的部分作为style,方便以后的视图使用,就不用重复写这么多次了

此时textView就可以用一个style 包含之前的属性
然后再添加一个 TextView 在alpha的下面
3.java 代码实现 在OnClick函数添加
case R.id.tv_scale://加载动画拿到 animation对象animation = AnimationUtils.loadAnimation(this, R.anim.scale_animation);view.startAnimation(animation);break;
效果:

sacle的基准点属性
| android:pivotX | ScaleAnimation(…, float pivotX, …) | (基准点)缩放起点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点) |
| android:pivotY | ScaleAnimation(…, float pivotY) | (基准点)缩放起点Y轴坐标,同上规律 |
修改一下上面代码:
让视图居中
效果:以视图的X、Y周轴中心作为基准点,放大两被的效果

三、平移动画(TranslateAnimation)
平移动画(Translate)-- 属性
| xml属性 | Java方法 | 说明 |
|---|---|---|
| android:fromXDelta | TranslateAnimation(float fromXDelta, …) | 起始点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点) |
| android:fromYDelta | TranslateAnimation(…, float fromYDelta, …) | 起始点Y轴从标,同上规律 |
| android:toXDelta | TranslateAnimation(…, float toXDelta, …) | 结束点X轴坐标,同上规律 |
| android:toYDelta | TranslateAnimation(…, float toYDelta) | 结束点Y轴坐标,同上规律 |
步骤:
1、anim文件夹中创建 xml文件
2、给布局中添加视图(省略了)
3、java代码的实现
case R.id.tv_translate://加载动画拿到 animation对象animation = AnimationUtils.loadAnimation(this, R.anim.translate_animation);view.startAnimation(animation);break;
效果:

| android:repeatCount | setRepeatCount(int) | 重复次数 |
| android:repeatMode | setRepeatMode(int) | 重复类型有两个值,reverse表示倒序回放,restart表示从头播放 |
两种重复模式 :restart 重头开始 reverse 原路返回
1、重头开始 restart
布局添加一个视图作为旋转动画的视图
3.java代码中添加一个点击事件
case R.id.tv_rotate://加载动画拿到 animation对象animation = AnimationUtils.loadAnimation(this, R.anim.rotate_animation);view.startAnimation(animation);break;
效果: 如果需要改基准点可以设置 pivot 属性

五、集合动画(AnimationSet)
一个持有其它动画元素alpha、scale、translate、rotate或者其它set元素的容器
将上述四种动画结合起来显示
例子1:anim文件夹中创建 set.xml 包含旋转和平移动画
2.添加视图(略)
3.添加点击事件(略)
效果

| android:startOffset | setStartOffset(long) | 调用start函数之后等待开始运行的时间,单位为毫秒 |
startOffset 函数可以这是等待多少时间之后再运行当前这个动画
拿上面的例子,让它先旋转完成再进行平移
效果:

Animation还有如下一些比较实用的方法介绍:
| Animation类的方法 | 解释 |
|---|---|
| reset() | 重置Animation的初始化 |
| cancel() | 取消Animation动画 |
| start() | 开始Animation动画 |
| hasStarted() | 判断当前Animation是否开始 |
| hasEnded() | 判断当前Animation是否结束 |
既然补间动画只能给View使用,那就来看看View中和动画相关的几个常用方法吧,如下:
| View类的常用动画操作方法 | 解释 |
|---|---|
| startAnimation(Animation animation) | 对当前View开始设置的Animation动画 |
| clearAnimation() | 取消当View在执行的Animation动画 |
特别特别注意:视图动画执行之后并未改变View的真实布局属性值。切记这一点,譬如我们在Activity中有一个Button在屏幕上方,我们设置了平移动画移动到屏幕下方然后保持动画最后执行状态呆在屏幕下方,这时如果点击屏幕下方动画执行之后的Button是没有任何反应的,而点击原来屏幕上方没有Button的地方却响应的是点击Button的事件。
动画监听
- 动画监听器接收来自动画的通知。通知表示与动画相关的事件,例如动画的结束或重复
- 使用方法:
Animation.addListener(new AnimatorListener() {@Overridepublic void onAnimationStart(Animation animation) {//动画开始时执行}@Overridepublic void onAnimationRepeat(Animation animation) {//动画重复时执行}@Overridepublic void onAnimationCancel()(Animation animation) {//动画取消时执行}@Overridepublic void onAnimationEnd(Animation animation) {//动画结束时执行}});
- 视图动画的监听只能通过此方式,且必须要复写全部4个方法。
- 属性动画时,可以采用
Animator.addListener(new AnimatorListenerAdapter(){ //复写指定方法 })------动画适配器AnimatorListenerAdapter中已经实现好每个接口
视图动画-插值器(Interpolator)
插值器是在XML中定义的一个动画修改器,它影响动画的变化率。这允许现有动画附加加速、减速、重复、反弹等效果。
继承关系

系统为我们提供了上图中的各种插值器,其都是实现了Interpolator接口的实现类,具体说明如下:
| java类 | XML 资源ID | 说明 |
|---|---|---|
| AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator | 先加速再减速 |
| AccelerateInterpolator | @android:anim/accelerate_interpolator | 持续加速 |
| AnticipateInterpolator | @android:anim/anticipate_interpolator | 先退后再加速前进 |
| AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 先退后再加速前进,超出终点后再回终点 |
| BounceInterpolator | @android:anim/bounce_interpolator | 结束时弹球效果 |
| CycleInterpolator | @android:anim/cycle_interpolator | 周期运动 |
| DecelerateInterpolator | @android:anim/decelerate_interpolator | 减速 |
| LinearInterpolator | @android:anim/linear_interpolator | 匀速 |
| OvershootInterpolator | @android:anim/overshoot_interpolator | 向前弹出一定值之后回到原来位置(快速完成动画,超出再回到结束样式) |
使用方法
- XML方式
...
- JAVA方式 使用不同的速率 直接new上面给出的类就行了 android定义好的
//加载动画拿到 animation对象animation = AnimationUtils.loadAnimation(this, R.anim.translate_animation);//创建插值器对象Interpolator interpolator = new OvershootInterpolator();//为动画添加插值器view.setInterpolator(interpolator);view.startAnimation(animation);
给动画多添加了一个插值器
自定义插值器
某些情景可能你会发现系统提供的插值器不能满足需求,此时我们需要自定义插值器。有两种实现方式:
XML自定义实现 和 JAVA代码实现方式
XML实现
- 在
res/anim/下创建filename.xml - 修改插值器属性(如下不作任何修改,则与系统预设插值器功能相同)
- 视图动画中引用该文件(资源引用为
@[package:]anim/filename)
XML实现方式本质就是修改系统提供的插值器的某些属性,具体可修改属性如下:
| 插值器 | 可修改属性 | 属性说明 |
|---|---|---|
| 无属性 | ||
| android:factor | Float,加速速率(默认值为1) | |
| android:tension | Float. 起始点后拉的张力数(默认值为2) | |
| android:tension android:extraTension | Float. 起始点后拉的张力数(默认值为2) Float. 拉力的倍数(默认值为1.5) | |
| 无属性 | ||
| android:cycles | Integer. 循环次数(默认为1) | |
| android:factor | Float. 减速的速率(默认为1) | |
| 无属性 | ||
| android:tension | Float. 超出终点后的张力(默认为2) |
JAVA方式
在此只讨论原理,不设计具体逻辑(奈何我是个数学渣,公式真的是一头雾水= =)
在前面继承关系的图中,我们可以看出所有插值器继承自BaseInterpolator,其又实现了Interpolator接口,而Interpolator接口继承自TimeInterpolator接口,TimeInterpolator接口中的唯一抽象方法为getInterpolation(float input),这个方法是由系统调用的,其中的参数input代表动画的时间,在0和1之间,也就是开始和结束之间。
我们可以看一下系统提供的插值器,如AccelerateDecelerateInterpolator,其源码极其极其简单,如下:
@HasNativeInterpolator
public class AccelerateDecelerateInterpolator extends BaseInterpolatorimplements NativeInterpolatorFactory {public AccelerateDecelerateInterpolator() {}@SuppressWarnings({"UnusedDeclaration"})public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {}public float getInterpolation(float input) {return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;}/** @hide */@Overridepublic long createNativeInterpolator() {return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator();}
}
可以看到,核心方法就是前面提到的getInterpolation(),其效果就是通过这一数学公式得来的,好久不看数学,已经快看不懂这个公式结果是什么了,汗颜= =
public float getInterpolation(float input) {return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;}
由此我们总结以下JAVA方式自定义插值器:
- 根据需求实现
TimeInterpolator接口 - 实现抽象方法
getInterpolation(),在该方法中处理逻辑 - 为动画设置该自定义插值器处。
属性动画的链接:转 Android的进阶4step1:动画基础2之属性动画(Property Animation)
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
