利用Canvas,自定义surfaceView实现测网速动态图标效果

    最近公司准备做一个测速功能,要求测速的时候有一个动画效果,既要显示实时测试的网速,又要在测速时有动画效果鉴于使用控件播放动画的消费太大,还是依然准备使用surfaceView来实现这个功能,主要用到了Canvas.drawArc(),Canvas.drawBitmap(),Canvas.drawText(),Canvas.drawCircle()四种功能,先上效果图;

利用Canvas,自定义surfaceView实现测网速动态图标效果_第1张图片

    先来解释一下里面用的几个画图方法:

canvas.drawArc(rect1, startDegree1, circleDegree, false, paintEmpty);//画圆弧
参数1:圆的范围大小 参数2:起始角度 参数3:圆心角角度,360为圆,180为半圆 参数4:是否有到圆心的连线 参数5:画笔Paint
//设置线条粗细 paintEmpty.setStrokeWidth(15);

 
canvas.drawCircle(point.x, point.y, radius, paintFill);//画圆
x,y为圆心,radius为半径,paintFill为画笔

canvas.drawBitmap(wifiBit, null, rect3, paintFill);//画一张bitmap
wifiBit是Bitmap文件,传入要画的图
第二个参数是一个rect型的参数,表示这张bitmap截取的范围,null为默认大小
第三个参数也是一个rect参数,表示要画在画布的哪个区域
第四个参数是画笔
canvas.drawText(speed+"kb/s",point.x,point.y+radius*2/3,paintText);
第一个参数是要显示的字符串
第二个参数比较复杂,如果再paintText画笔中设置了paintText.setTextAlign(Paint.Align.CENTER);,第
二个参数则为这个字符串的中间点坐标,如果不是则是左上角左边

第三个参数是textview的baseline,也就是下底边的y坐标

第四个参数是画笔


下面是这个动画控件的源代码:

public class CircleView extends SurfaceView implements SurfaceHolder.Callback {

    private Context mContext;
    private SurfaceHolder holder;
    private RenderThread renderThread;
    private boolean isDraw = false;// 控制绘制的开关
    private boolean isFristDraw = true;//初次声明控件

    private Paint paintFill;//画笔、实心
    private Paint paintEmpty;//画笔 、空心
    private Paint paintText;//画笔,文字
    private static final int WAVE_PAINT_COLOR = Color.BLUE;// 画笔颜色
    private static final int INVALIDATE_DURATION = 20; //每次刷新的时间间隔
    private static int boder = 40;//边界
    private int viewHeight;//View高度
    private int viewWidth;//View宽度
    private Point point = new Point();//圆心
    private int radius;//实心圆半径
    private int circleRadius1;//空心圆弧半径1
    private int circleRadius2;//空心圆弧半径1
    private RectF rect1;//空心圆弧1
    private RectF rect2;//空心圆弧2
    private RectF rect3;//wifi图案
    private int startDegree1 = 0;//圆弧1起始度数
    private int startDegree2 = 60;//圆弧2起始度数
    private int circleDegree = 320;//弧度
    private Bitmap wifiBit;//wifi图标
    private Bitmap circleBit;//圆圈图标
    private String speed = "0";//网速

    private DecimalFormat df = new DecimalFormat("###.00");//速度保留两位小数

    public CircleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        holder = this.getHolder();
        holder.addCallback(this);
        mContext = context;
        initPaint();
        renderThread = new RenderThread();
    }

    public CircleView(Context context) {
        super(context);
        holder = this.getHolder();
        holder.addCallback(this);
        mContext = context;
        initPaint();
        renderThread = new RenderThread();
    }

    public void initPaint() {
        paintFill = new Paint();
        //颜色
        paintFill.setColor(WAVE_PAINT_COLOR);
        //抗锯齿
        paintFill.setAntiAlias(true);
        //设置风格为实线
        paintFill.setStyle(Paint.Style.FILL);
        //设置透明度
        paintFill.setAlpha(100);
        paintEmpty = new Paint();
        //颜色
        paintEmpty.setColor(WAVE_PAINT_COLOR);
        //抗锯齿
        paintEmpty.setAntiAlias(true);
        //设置透明度
        paintEmpty.setAlpha(80);
        //设置风格为实线
        paintEmpty.setStyle(Paint.Style.STROKE);
        //设置线条粗细
        paintEmpty.setStrokeWidth(15);

        paintText = new Paint();
        paintText.setTextAlign(Paint.Align.CENTER);
        paintText.setAntiAlias(true);
//        paintText.setStrokeWidth(5);
        paintText.setColor(Color.WHITE);
        paintText.setTextSize(UiUitls.dipToPx(mContext,18));
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        //surface被创建,开始播放动画
        if(isFristDraw) {
            isDraw = true;
            renderThread.start();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        //surface被销毁
        isDraw = false;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        viewHeight = h;
        viewWidth = w;
        DefineFunction();
    }

    //定义初始数据
    private void DefineFunction() {
        point.x= viewWidth/2;
        point.y= viewHeight/2;
        if(viewHeight>viewWidth) {//半径为短边的四分之一
            radius = viewWidth/4;
        }else{
            radius = viewHeight/4;
        }
        boder = radius/8;//设置圆弧边界参数
        //设置圆弧线条粗细
        paintEmpty.setStrokeWidth(boder/2);
        circleBit = BitmapFactory.decodeResource(getResources(), R.drawable.icon_circle);
        wifiBit = BitmapFactory.decodeResource(getResources(), R.drawable.icon_wifi);
        circleRadius1 = radius+boder;
        rect1 = new RectF(point.x-circleRadius1,point.y-circleRadius1,point.x+circleRadius1,point.y+circleRadius1);
        circleRadius2 = radius+2*boder;
        rect2 = new RectF(point.x-circleRadius2,point.y-circleRadius2,point.x+circleRadius2,point.y+circleRadius2);
        rect3 = new RectF(point.x-radius/2,point.y-radius/2,point.x+radius/2,point.y+radius/4);
    }

    private class RenderThread extends Thread {
        @Override
        public void run() {
            // 不停绘制界面
            while (isDraw) {
                drawUI();
                try {
                    sleep(INVALIDATE_DURATION);//延时20毫秒再画下一帧
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            super.run();
        }
    }

    /**
     * 界面绘制
     */
    private void drawUI() {
        Canvas canvas = holder.lockCanvas();
        //设置画布抗锯齿
        canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
        canvas.drawColor(Color.WHITE);
        try {
            //绘制图形
          synchronized (this) {
              startDrawCircle(canvas);
          }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            holder.unlockCanvasAndPost(canvas);
        }
    }





    /**
     * 绘制图像
     */
    private void startDrawCircle(Canvas canvas) {
        canvas.drawCircle(point.x, point.y, radius, paintFill);
        canvas.drawBitmap(wifiBit, null, rect3, paintFill);
        canvas.drawText(speed+"kb/s",point.x,point.y+radius*2/3,paintText);
        if(startDegree1<360){
            startDegree1 = startDegree1+2;
        }else{
            startDegree1=0;
        }
        if(startDegree2<360){
            startDegree2 = startDegree2+4;
        }else{
            startDegree2 = 0;
        }
        /**
         * 参数1:圆的范围大小
         * 参数2:起始角度
         * 参数3:圆心角角度,360为圆,180为半圆
         * 参数4:是否有到圆心的连线
         * 参数5:画笔Paint**/
        canvas.drawArc(rect1, startDegree1, circleDegree, false, paintEmpty);
        canvas.drawArc(rect2, startDegree2, circleDegree, false, paintEmpty);
        if(isFristDraw){
            isDraw = false;
            isFristDraw = false;
        }

    }

    /**
     * 重新开始动画
     */
    public void startCircle() {
        if (!isDraw) {
            isDraw = true;
            renderThread = new RenderThread();
            renderThread.start();
        }
    }

    /**
     * 停止动画
     */
    public void stopCircle() {
        isDraw = false;
    }

    /**
     * 获得画笔
     */
    public Paint getPaint() {
        return paintFill;
    }

    /**
     * 设置速度
     */
    public void setSpeed(float speed) {
        this.speed = df.format(speed);
    }
}






   

你可能感兴趣的:(android,动画,canvas,控件,SurfaceView)