一个好看的APP,都有不少精致的动画效果。熟练运用各种动画技术,可让我们的APP灼灼生辉。Android在技术上把动画分为了三类,分别是帧动画FrameAnimation、补间动画TweenAnimation、属性动画,其中补间动画又分做五种:深浅动画AlphaAnimation、平移动画TranslateAnimation、缩放动画ScaleAnimation、旋转动画RotateAnimation、组合动画AnimationSet。网上对这些动画的说明资料有不少,所以博主就不打算介绍它们的基本用法了,还是说说另外的一些常用动画。 首先介绍的是圆弧进度动画,像我们下载文件或者是做其他什么事情,都想知道当前到什么进度了。在Windows下常用来表达的是细长的进度条,但在手机上因为屏幕限制,我们更喜欢展示圆形或弧形的进度圈。所以接下来说的便是这个进度圆圈的动画,同时也正好与上一节自定义视图的绘制方法结合起来,复习复习加深巩固。 绘制圆弧动画,主要思路在一段指定的时间内,持续间隔地绘制一个扇形或圆弧,如同放电影的原理那样,每秒连续播放二三十张图片,连起来整个画面就动了。 其次还要进行一些参数的设置,如设置该圆圈的位置、开始和结束的角度,以及转动的速率等等,还有画笔的颜色、粗细、样式等等。 另外为了区分处理背景和动画,我们还要处理背景视图(用于衬托动画)、前景视图(用于展示动画)。 剩下的就是在绘制的时候做好每帧之间的延迟时间,重绘视图可用invalidate和postInvalidate方法,延迟可用Thread.sleep和Handler.postDelayed方法。 实现代码不难,直接贴出来了
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Paint.Style;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.RelativeLayout;
public class CicleAnimation extends RelativeLayout {
private final static String TAG = "CicleAnimation";
private RectF mRect = new RectF(10, 10, 160, 160);
private int mBeginAngle = 0;
private int mEndAngle = 270;
private int mFrontColor = 0xff00ff00;
private float mFrontLine = 5;
private Style mFrontStyle = Style.STROKE;
private int mShadeColor = 0xffeeeeee;
private float mShadeLine = 5;
private Style mShadeStyle = Style.STROKE;
private ShadeView mShadeView;
private FrontView mFrontView;
private int mRate = 2;
private int mDrawTimes;
private int mInterval = 70;
private int mFactor;
private Context mContext;
private int mSeq = 0;
private int mDrawingAngle = 0;
public CicleAnimation(Context context) {
super(context);
mContext = context;
}
public CicleAnimation render() {
mShadeView = new ShadeView(mContext);
this.addView(mShadeView);
mFrontView = new FrontView(mContext);
this.addView(mFrontView);
refresh();
return this;
}
public void refresh() {
mSeq = 0;
mDrawingAngle=0;
mDrawTimes = mEndAngle/mRate;
mFactor = mDrawTimes/mInterval + 1;
Log.d(TAG, "mDrawTimes="+mDrawTimes+",mInterval="+mInterval+",mFactor="+mFactor);
mFrontView.invalidateView();
}
public void setRect(int left, int top, int right, int bottom) {
mRect = new RectF(left, top, right, bottom);
}
public void setAngle(int begin_angle, int end_angle) {
mBeginAngle = begin_angle;
mEndAngle = end_angle;
}
//speed:每次移动几个度数 frames:每秒移动几帧
public void setmRate(int speed, int frames) {
mRate = speed;
mInterval = 1000/frames;
}
public void setFront(int color, float line, Style style) {
mFrontColor = color;
mFrontLine = line;
mFrontStyle = style;
}
public void setShade(int color, float line, Style style) {
mShadeColor = color;
mShadeLine = line;
mShadeStyle = style;
}
class ShadeView extends View {
Paint paint;
public ShadeView(Context context) {
super(context);
paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
paint.setColor(mShadeColor);
paint.setStrokeWidth(mShadeLine);
paint.setStyle(mShadeStyle);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(mRect, mBeginAngle, 360, false, paint);
}
}
class FrontView extends View {
Paint paint;
public FrontView(Context context) {
super(context);
paint = new Paint();
paint.setAntiAlias(true); //设置画笔为无锯齿
paint.setDither(true); //防抖动
paint.setColor(mFrontColor); //设置画笔颜色
paint.setStrokeWidth(mFrontLine); //线宽
paint.setStyle(mFrontStyle); //画笔类型 STROKE空心 FILL 实心
//paint.setStrokeJoin(Paint.Join.ROUND); //画笔接洽点类型 如影响矩形直角的外轮廓
paint.setStrokeCap(Paint.Cap.ROUND); ////画笔笔刷类型 如影响画笔的始末端
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(mRect, mBeginAngle, (float) (mDrawingAngle), false, paint);
}
public void invalidateView(){
handler.postDelayed(drawRunnable, 0);
}
private Handler handler = new Handler();
Runnable drawRunnable = new Runnable() {
@Override
public void run() {
if (mDrawingAngle >= mEndAngle) {
mDrawingAngle = mEndAngle;
invalidate();
//移除当前Runnable
handler.removeCallbacks(drawRunnable);
} else {
mDrawingAngle = mSeq*mRate;
mSeq++;
handler.postDelayed(drawRunnable, (long) (mInterval-mSeq/mFactor));
invalidate();
}
}
};
}
}
调用的代码如下
Button btn_play = (Button) findViewById(R.id.btn_play);
btn_play.setOnClickListener(this);
LinearLayout ll_layout = (LinearLayout) findViewById(R.id.ll_layout);
mCircle = new CicleAnimation(this);
ll_layout.addView(mCircle);
mCircle.render();
下面是圆弧动画的效果图