Android开发笔记(十四)圆弧进度动画CircleAnimation

一个好看的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();

下面是圆弧动画的效果图

点击下载本文用到的圆弧进度动画代码

点此查看Android开发笔记的完整目录

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券