心灵鸡汤:真正成功的人生,不在于成就的大小,而在于你是否努力地去实现自我,喊出自己的声音,走出属于自己的道路。
不积跬步,无以至千里;不积小流,无以成江海。学习任何东西我们都离不开扎实的基础知识,这次我们重温Android中让我们又爱又恨的动画。即便没有很好的算法思想,但是掌握了Animation的基础,我们同样可以通过动画给我们的App增色不少。
在我们日常开发中,我们都希望我们的App拥有及其炫酷的动画效果,除了一些SDK提供给我们拥有炫酷动画效果的控件外,都需要我们自己来实现。在Android系统中,官方给我们提供了两种类型的动画:属性动画(Property Animation) 和 视图动画(View Animation),而视图动画又包含了两种类型:补间动画(Tween animation) 和 帧动画(Frame animation)。
Property Animation(属性动画):通过改变对象的属性来实现动画效果。
View Animation(视图动画):包括了以下两种动画类型。
Tween Animation(补间动画):通过对视图进行一系列的动作变化实现动画效果。
Frame Animation(帧动画):通过一组图片有序播放实现动画视觉效果。
为此,由于篇幅过长,笔主通过三篇博文来重温Animation的相关基础知识,内容主要作为抛砖引玉,围绕这三种动画作简单的介绍,因为所有的动画都是以这几种动画为基础,配合其他的技术,例如自定义View、还有一些曲线函数等,做出很多炫酷的效果。但是,炫酷动画万万千,我们做的每一个动画需求都是源自设计师的灵感,所以这篇文章就不对动画的高阶讲解,相反,是作为抛砖引玉,所以如果你已经非常熟悉动画相关,可以跳过,但是如果你对动画还是不了解,不妨继续看下去。
想要了解更多,请参考官方文档:Animation Resources
本文首先对View Animation的Tween Animation做介绍,如果大家有兴趣,可以继续阅读本动画系列其他相关文章,作者也在不断更新完善相关内容,希望大家可以指出有误之处。
Android基础夯实–重温动画(二)之Frame Animation
Android基础夯实–重温动画(三)之初识Property Animation
Android基础夯实–重温动画(四)之属性动画 ValueAnimator详解
Tween Animation,翻译为补间动画,是View Animation两种中的一种,也是我们在Android开发中使用频率最高的一种动画,因为它能够基本满足我们的动画需要,主要是通过对控件实现透明度(alpha)、尺寸(scale)、位置(translate)、旋转rotate)进行改变,通过集合(set)的方式,实现连续的动画效果。但是需要注意的是,使用TweenAnimation,我们不能改变view的属性。
Tween Animation是View Animation其中之一,Tween Animation可以实现对控件实现以下四种变换:
之所以可以这样,是因为四个便签都有对应的Java类:AlphaAnimation, RotateAnimation, ScaleAnimation, TranslateAnimation。
所在包:android.view.animation.*
都继承于父类:android.view.animation.Animation
Tween Animation的所有效果都是继承于Animation类,Animation类作为一个抽象类,提供了动画基本属性的实现,需要由具体的子类来具体实现。
mAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// 动画执行时
}
@Override
public void onAnimationEnd(Animation animation) {
// 动画结束时
}
@Override
public void onAnimationRepeat(Animation animation) {
// 动画循环时
}
});
Java方法:setDetachWallpaper(boolean detachWallpaper)
Java方法:setDuration(long)
Java方法:setFillAfter(boolean)
Java方法:setFillBefore(boolean)
Java方法:setFillEnabled(boolean)
Java方法:setInterpolator(Interpolator)
Java方法:setRepeatCount(int)
Java方法:setRepeatMode(int)
Java方法:setStartOffset(long)
Java方法:setZAdjustment(int)
Interpolator,又名插值器,主要是实现动画的速率变化。Interpolator作为一个接口,它的抽象子类BaseInterpolator实现Interpolator接口,在BaseInterpolator的子类就是一系列Android提供的插值器。
用法:
以下为Andorid所提供的所有插值器:
关于以上所有插值器的Demo:
AnimationSet是动画中非常重要的概念,继承于Animation类,它将很多独立的动画包裹到一个集合内,形成一个共同作用的动画效果。例如,我们会在res/anim/目录下的xml文件里面这样实现一个包含多种效果的动画(透明度、尺寸、位置、旋转):
效果如下:
当然,你可以使用Java代码来实现,逻辑和在XML中实现的是一样的,如下:
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding mainBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
//参数为false,不共享Interpolator
AnimationSet set = new AnimationSet(false);
set.setFillAfter(true);
// Scale动画
ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.4f, 1.0f, 0.6f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
scaleAnimation.setDuration(1500);
set.addAnimation(scaleAnimation);
// mSet集合
AnimationSet mSet = new AnimationSet(true);
mSet.setInterpolator(new AccelerateInterpolator());
mSet.setDuration(1000);
mSet.setStartOffset(1500);
// Scale动画
ScaleAnimation mScaleAnimation = new ScaleAnimation(1.4f, 0.0f, 0.6f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
mSet.addAnimation(mScaleAnimation);
// Rotate动画
RotateAnimation mRotateAnimation = new RotateAnimation(0.0f, -45.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
mSet.addAnimation(mRotateAnimation);
set.addAnimation(mSet);
mainBinding.image.startAnimation(set);
}
}
void addAnimation (Animation a): 把一个子动画加到Animation Set中去。
long computeDurationHint (): 获取最长时间的子动画的时间,单位毫秒。
List getAnimations (): 获取所有子动画对象的集合。
long getStartTime ():获取动画什么时候应该播放,如果方法返回常量 START_ON_FIRST_FRAME (-1),表明动画未播放。
boolean getTransformation (long currentTime,
Transformation t): 获取帧动画执行到目前时的变换信息,存到Transformation中,主要用作调试用。
例如我们需要当前Scale动画的变换信息:
Transformation tf = new Transformation();
if (scaleAnimation!=null){
scaleAnimation.getTransformation(AnimationUtils.currentAnimationTimeMillis(), tf);
System.out.println("Matrix:" + tf.getMatrix());
System.out.println("Alpha:" + tf.getAlpha());
System.out.println("TransformationType:" + tf.getTransformationType());
}
void initialize (int width,
int height,
int parentWidth,
int parentHeight): 初始化动画的宽高和父动画的宽高。
void reset (): 重置动画的初始状态。
void restrictDuration (long durationMillis): 限制动画不能超过durationMillis个毫秒。
boolean willChangeBounds (): 动画是否会改变view的尺寸边界。true为会。
boolean willChangeTransformationMatrix (): 动画是否会改变view的矩阵。
AlphaAnimation是继承于Animation的一个动画类型,它通过控制控件的透明度变化来实现动画效果,如我们常见的淡入淡出效果就是通过AlphaAnimaiton实现。
不多说,我们来通过例子看一下AlphaAnimation的实现消失动画效果:
还是有两种写法,一种在XML里定义动画的样式,一种在Java代码里实现动画的样式。
在res/anim目录下定义alpha.xml文件,在文件内写:
在Activity中加载xml文件,并绑定控件播放动画:
AlphaAnimation animation = (AlphaAnimation) AnimationUtils.loadAnimation(getApplicationContext(), R.anim.alpha);
image.startAnimation(animation);
直接在Java代码中实现:
AlphaAnimation animation = new AlphaAnimation(1.0f, 0.0f);
animation.setDuration(2500);
mBinding.image.startAnimation(animation);
ScaleAnimation是继承于Animation的一个动画类型,它通过控制控件的尺寸大小来实现动画效果,如我们常见的放大,缩小效果就是通过ScaleAnimation实现。
同样,先示范:
还是有两种写法,一种在XML里定义动画的样式,一种在Java代码里实现动画的样式。
在res/anim目录下定义scale.xml文件,在文件内写:
在Activity中加载xml文件,并绑定控件播放动画:
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.scale);
image.startAnimation(animation);
在Java代码中实现:
AnimationSet set = new AnimationSet(false);
set.setFillAfter(true);
// 构造函数 fromX, toX, fromY, toY, pivotXType, pivotXValue, pivotYType, pivotYValue
// pivotXType和pivotYType都有三种取值:Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, Animation.RELATIVE_TO_PARENT
ScaleAnimation sa1 = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f, Animation.RELATIVE_TO_SELF,0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
sa1.setDuration(1500);
ScaleAnimation sa2 = new ScaleAnimation(1.0f, 0.0f, 1.0f, 0.0f, Animation.RELATIVE_TO_SELF,0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
sa2.setDuration(1500);
sa2.setStartOffset(1500);
set.addAnimation(sa1);
set.addAnimation(sa2);
mBinding.image.startAnimation(set);
RotateAnimation是继承于Animation的一个动画类型,它通过控制控件旋转来实现动画效果,如我们常见的转动效果就是通过RotateAnimation实现。
先看一个小demo:
还是有两种写法,一种在XML里定义动画的样式,一种在Java代码里实现动画的样式。
在res/anim目录下定义rotate.xml文件,在文件内写:
在Activity中加载xml文件,并绑定控件播放动画:
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rotate);
image.startAnimation(animation);
在Java代码中实现:
AnimationSet set = new AnimationSet(false);
set.setFillAfter(true);
RotateAnimation ra1 = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
ra1.setDuration(1000);
RotateAnimation ra2 = new RotateAnimation(0f, -1800f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
ra2.setDuration(1500);
ra2.setStartOffset(1000);
set.addAnimation(ra1);
set.addAnimation(ra2);
mBinding.image.startAnimation(set);
TranslateAnimation是继承于Animation的一个动画类型,它通过控制控件位置变化来实现动画效果,如我们常见的位移效果就是通过TranslateAnimation实现。
TranslationAnimation相关的小Demo,围绕四周转动:
只展示一种写法,Java代码实现方式同上:
在res/anim目录下定义translate.xml文件,在文件内写:
在Activity中加载xml文件,并绑定控件播放动画:
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.translate);
mBinding.image.startAnimation(animation);
对于很多比较少接触动画的同学,可能都会比较反感,因为觉得动画篇的东西又多又难学,其实不然,就像我们这篇所介绍的Tween Animation,虽然有很多种动画类型,但是几种都是基于父类Animation类,然后在它的基础上进行了稍微扩展,所以当我们认真静下来去看的时候,我们会发现,其实也不过如此。Animation在实际开发中非常常见,尤其本篇所说的最基本的Tween Animation。在Android已经达到了如此成熟的今天,市场上的应用很大一部分依靠炫酷的动画效果来吸引用户,所以掌握动画会帮助你在日后开发中有很大的帮助,不说其他,早点下班是必须的。