上一篇我们说道了Android apidemos导入的一些相关问题。现在这些demo已经成功导入了Android studio里,接下来我们就要认真分析这些demo了,我们以最新的23版本为标准,先从最简单的activity说起吧。下面我们开始分析app/activity下的第一个demo—-Animaition
Animaition是什么?
Animaitionc就是动画,在Android中Animaition很基本可以分为:以下几种
- Tween Animation(补间动画) 只能对View对象进行操作,不对view有任何实际的改变
- Frame Animation(帧动画)由一组图像顺序显示显示动画
- Property Animation(属性动画)补间动画加强版,不局限于view,并可以真正的改变属性等
今天我们只关注activity的Animation。具体位置在app->Animaition.java。
先来看一段代码
Button button = (Button)findViewById(R.id.fade_animation);
button.setOnClickListener(mFadeListener);
button = (Button)findViewById(R.id.zoom_animation);
button.setOnClickListener(mZoomListener);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
button = (Button)findViewById(R.id.modern_fade_animation);
button.setOnClickListener(mModernFadeListener);
button = (Button)findViewById(R.id.modern_zoom_animation);
button.setOnClickListener(mModernZoomListener);
button = (Button)findViewById(R.id.scale_up_animation);
button.setOnClickListener(mScaleUpListener);
button = (Button)findViewById(R.id.zoom_thumbnail_animation);
button.setOnClickListener(mZoomThumbnailListener);
button = (Button)findViewById(R.id.no_animation);
button.setOnClickListener(mNoAnimationListener);
} else {
findViewById(R.id.modern_fade_animation).setEnabled(false);
findViewById(R.id.modern_zoom_animation).setEnabled(false);
findViewById(R.id.scale_up_animation).setEnabled(false);
findViewById(R.id.zoom_thumbnail_animation).setEnabled(false);
}
从这段代码中我们很清楚的看到,mFadeListener和mZoomListener是不区分版本的,但是其余的四个动画对Android的版本进行了区分,只有4.1以上的版本才可以使用。也就是是说要兼容更多的版本的话,要采用前两种动画的方式,这个我们最后在介绍。
首先看一下mModernFadeListener主要是做了什么
private OnClickListener mModernFadeListener = new OnClickListener() {
public void onClick(View v) {
ActivityOptions opts = ActivityOptions.makeCustomAnimation(Animation.this,
R.anim.fade, R.anim.hold);
startActivity(new Intent(Animation.this, AlertDialogSamples.class), opts.toBundle());
}
};
代码很简单,只是通过ActivityOptions.makeCustomAnimation方法创建了一个ActivityOptions对象,然后在启动另一个activity的时候作为参数传递了进去,就完成了给activity设置动画的功能。那么什么是ActivityOptions呢?
ActivityOptions是Android 4.1(API16)提供的一个新类,用来实现Activity的切换动画,这也是为什么在前面要区分版本,因为只有API16之后才会有。
ActivityOptions类提供了三个方法
- makeScaleUpAnimation() 创建一个动画,能够从屏幕指定的位置和指定的大小拉伸一个活动窗口。例如,当打开一个应用时,Android 4.1的主屏幕使用了这个方法。
- makeThumbnailScaleUpAnimation() 创建一个动画,能够从屏幕指定的位置和提供的缩略图拉伸一个活动窗口。例如,在Android 4.1的最近使用程序窗口中,当往回一个应用程序时使用了这个动画。
- makeCustomAnimation() 创建一个动画,由你自己的资源所定义:一个用来定义活动开启的动画,一个用来定义活动被关闭的动画。
-
通过这三个方法中的一个就可以创建一个ActivityOptions示例,然后调用toBundle()方法获取一个Bundle对象,传递给startActivity方法。
接下来就是传递的两个xml文件了,我们简单看一下:
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator"
android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_longAnimTime" />
这是配置一个动画的xml文件,alpha节点表示这是一个透明的动画,属性的含义分别是:
- interpolator 插入器 简单点说就是设置动画播放的速率
- fromAlpha 动画开始的透明度
- toAlpha 动画结束的透明度
- duration 动画播放时间
为什么要传两个xml文件呢?相信聪明的朋友已经想到了,就是一个进入activity的动画,一个是离开的动画,我们看一下API就知道了
public static ActivityOptions makeCustomAnimation(Context context,
int enterResId, int exitResId) {
return makeCustomAnimation(context, enterResId, exitResId, null, null);
}
enterResId和exitResId看名字就足以说明问题了,到这里我们就把一个activity的简单动画分析完了,但是我们需要注意的这在4.1前的版本版本是不适用的。
接下来看mModernZoomListener做了什么:
private OnClickListener mModernZoomListener = new OnClickListener() {
public void onClick(View v) {
ActivityOptions opts = ActivityOptions.makeCustomAnimation(Animation.this,
R.anim.zoom_enter, R.anim.zoom_enter);
startActivity(new Intent(Animation.this, AlertDialogSamples.class), opts.toBundle());
}
};
这个和上面的基本上一样了,只是xml配置的动画不一样罢了,就不在赘述。继续看mScaleUpListener:
private OnClickListener mScaleUpListener = new OnClickListener() {
public void onClick(View v) {
ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(
v, 0, 0, v.getWidth(), v.getHeight());
startActivity(new Intent(Animation.this, AlertDialogSamples.class), opts.toBundle());
}
};
这个就有意思了,没有用到xml文件,而是直接通过上面我们介绍到得makeScaleUpAnimation方法创建的,我们来看看makeScaleUpAnimation内部是怎么实现的
public static ActivityOptions makeScaleUpAnimation(View source,
int startX, int startY, int width, int height) {
ActivityOptions opts = new ActivityOptions();
opts.mPackageName = source.getContext().getPackageName();
opts.mAnimationType = ANIM_SCALE_UP;
int[] pts = new int[2];
source.getLocationOnScreen(pts);
opts.mStartX = pts[0] + startX;
opts.mStartY = pts[1] + startY;
opts.mWidth = width;
opts.mHeight = height;
return opts;
}
先研究一下在调用这个方法的时候需要传入五个参数:
- View source 动画作用的对象View,这里我们传入的其实就是button,所以动画会作用在button上
- int startx 动画开始的X坐标
- int starty 动画开始的Y坐标 这两个参数都是传的0,也是会从初始位置开始启动
- int width 被拉伸view对象的初始宽度 这次我们直接传的就是view的宽度
- int height 被拉伸view对象的初始高度 这次我们直接传的就是view的高度
其实makeScaleUpAnimation就是内部自己new一个ActivityOptions对象出来,然后把传入的参数传递给ActivityOptions而已,不过这里作用的对象是传入的View对象而不是activity哦。
最后要看的就是的就是mZoomThumbnailListener啦
public void onClick(View v) {
v.setDrawingCacheEnabled(true); //激活绘制图形的缓存
v.setPressed(false);//取消按下的状态
v.refreshDrawableState();//刷新状态
Bitmap bm = v.getDrawingCache();//拿到绘制的图像
ActivityOptions opts = ActivityOptions.makeThumbnailScaleUpAnimation(
v, bm, 0, 0);
startActivity(new Intent(Animation.this, AlertDialogSamples.class), opts.toBundle());
v.setDrawingCacheEnabled(false);//关闭缓存
}
我们看到这次又是在View上进行了就地取材,拿到了view的图像然后传makeThumbnailScaleUpAnimation创建出一个ActivityOptions对象,从注释中我们基本了它都做了哪些操作,这个执行顺序是不能变的尤其是在
getDrawingCache之前一定要调用setDrawingCacheEnabled哦,否则就会拿到一个空的图像。接下来就是
makeThumbnailScaleUpAnimation了,我们只看它最终创建的地方
private static ActivityOptions makeThumbnailAnimation(View source,
Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
boolean scaleUp) {
ActivityOptions opts = new ActivityOptions();
opts.mPackageName = source.getContext().getPackageName();
opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN;
opts.mThumbnail = thumbnail;
int[] pts = new int[2];
source.getLocationOnScreen(pts);
opts.mStartX = pts[0] + startX;
opts.mStartY = pts[1] + startY;
opts.setOnAnimationStartedListener(source.getHandler(), listener);
return opts;
}
其实makeThumbnailScaleUpAnimation最后调用的是makeThumbnailAnimation放大创建的对象,并且传入的listener为null和true来开启动画,帮我们省略了一些细节,简化了参数。其余的参数我们在上面已经介绍了,只不过这次作用是bitmap而不是view了,总的来说区别不大。
最后就是介绍一下版本通用的了
public void onClick(View v) {
startActivity(new Intent(Animation.this, AlertDialogSamples.class));
overridePendingTransition(R.anim.fade, R.anim.hold);
}
就是了overridePendingTransition方法了,传入两个xml文件就搞定了如果考虑到适配到低版本的话,优先考虑这种方式,而且不受限制。高版本的话当然建议选用ActivityOptions创建了。总的来说其实系统提供这些已经基本满足日常使用了,如果有特殊需求使用一些自定义动画即可,而随着Android手机硬件性能和系统性能的提高,切换动画的时间已经很短了,很难看出有很大区别了。
今天activity的切换动画就介绍到这里了,在实际开发过程中按照实际需求进行选择就好。