安卓自定义刻度盘控件

思路参考网上大神的,该博客用于一起学习,谢谢^ ^

刻度盘gif效果图:
安卓自定义刻度盘控件_第1张图片

思路:

1 自定义view的步骤,根据需求extends View
重写onMeasure onLayout onDraw 测量 排版 绘制
根据需求,没有继承ViewGroup onLayout不必重写

2 onMeasure利用宽高约束获得xml中设置宽高,取最小为绘制圆弧的直径,确定圆弧所在的矩形区域,因为绘制圆的api需要传RectF对象
// oval是一个RectF对象为一个矩形
// startAngle为圆弧的起始角度
// sweepAngle为圆弧的经过角度(扫过角度)
// useCenter为圆弧是一个boolean值,为true时画的是圆弧,为false时画的是割弧
// paint为一个画笔对象
canvas.drawArc(oval,startAngle,sweepAngle,useCenter,paint);
3 绘制刻度:画布平移到圆心,旋转画布,绘制刻度。(根据实际需求灵活绘制)
4 提供对外方法,改变角度重新调用ondraw方法绘制(考虑线程)
5 提供接口,功能扩展

先贴代码,注释很全,之前先贴几个问题
view的坐标(每个view都已自己为中心)望舒大哥博客下载的:
安卓自定义刻度盘控件_第2张图片
canvas旋转 顺时针rotate方法参数为正顺时针,负数为逆时针,中心是坐标原点

code:

package com.weiyu.sharedanimator;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import java.util.Timer;
import java.util.TimerTask;

/**
 * 作者:haoran   on https://github.com/woaigmz 2017/5/27.
 * 邮箱:[email protected]
 * 说明:
 */

public class DivisionCircleView extends View {

    private int len;
    private RectF oval;
    //起始角度
    private float startAngle=120;
    //经过角度
    private float sweepAngle=300;
    // 刻度经过角度范围
    private float targetAngle = 300;
    private Paint paint;
    private float radius;

    // 绘制文字
    private Paint textPaint;
    // 画水球的画笔
    private Paint waterPaint;
    boolean useCenter = false;


    public DivisionCircleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initPaint();
    }

    /**
     *1  初始化画笔对象
     */
    private void initPaint() {

        paint =new Paint();
        //设置画笔颜色
        paint.setColor(Color.WHITE);
        //设置画笔抗锯齿
        paint.setAntiAlias(true);
        //让画出的图形是空心的(不填充)
        paint.setStyle(Paint.Style.STROKE);

        //文本画笔
        textPaint = new Paint();
        textPaint.setARGB(255, 255, 255, 255);
        textPaint.setAntiAlias(true);

        //水波纹画笔
        waterPaint = new Paint();
        waterPaint.setAntiAlias(true);
    }

    /**
     *2  来测量限制view为正方形
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        //以最小值为刻度区域正方形的长
        len = Math.min(width, height);
        //确定圆弧所在的矩形区域
        oval = new RectF(0, 0, len, len);
        radius = len/2;
        //设置测量高度和宽度
        setMeasuredDimension(len,len);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 3 绘制圆弧
        // oval是一个RectF对象为一个矩形
        // startAngle为圆弧的起始角度
        // sweepAngle为圆弧的经过角度(扫过角度)
        // useCenter为圆弧是一个boolean值,为true时画的是圆弧,为false时画的是割弧
        // paint为一个画笔对象
        canvas.drawArc(oval,startAngle,sweepAngle,useCenter,paint);
        // 4 画刻度线
        drawViewLine(canvas);
    }

    /**
     * 绘制刻度线
     * @param canvas
     */
    private void drawViewLine(Canvas canvas) {
        canvas.save();
        //移动canvas
        canvas.translate(radius,radius);
        //旋转canvas
        canvas.rotate(30);
        //普通刻度
        Paint linePatin=new Paint();
        //设置普通刻度画笔颜色
        linePatin.setColor(Color.WHITE);
        //线宽
        linePatin.setStrokeWidth(2);
        //设置画笔抗锯齿
        linePatin.setAntiAlias(true);
       /* //画一条刻度线
        canvas.drawLine(0,radius,0,radius-40,linePatin);*/
        //画101条刻度线
        //确定每次旋转的角度
        float rotateAngle=sweepAngle/99;
        //绘制需要有颜色部分的画笔
        Paint targetLinePatin=new Paint();
        targetLinePatin.setColor(Color.GREEN);
        targetLinePatin.setStrokeWidth(2);
        targetLinePatin.setAntiAlias(true);
        //记录已经绘制过的有色部分范围(角度float)
        float hasDraw=0;
        for(int i=0;i<100;i++){
          /*  //画一条刻度线
            canvas.drawLine(0,radius,0,radius-40,linePatin);*/
            //有色和无色分别用不同颜色
            if (hasDraw <= targetAngle && targetAngle != 0) {
                //计算已经绘制的比例
                float percent=hasDraw/sweepAngle;
                int red= 255-(int) (255*percent);
                int green= (int) (255*percent);
                //角度变化颜色值由外界传入而改变
                if (onAngleColorListener!=null){
                    onAngleColorListener.colorListener(red,green);
                }
                targetLinePatin.setARGB(255,red,green,0);

                canvas.drawLine(0, radius, 0, radius - 40, targetLinePatin);
            } else {
                canvas.drawLine(0,radius,0,radius-40,linePatin);
            }
            hasDraw += rotateAngle;
            canvas.rotate(rotateAngle);
        }

        //操作完成后恢复状态
        canvas.restore();
    }

    //判断是否在动
    private boolean isRunning;
    //判断是回退的状态还是前进状态
    private int state = 1;

    /**
     * 5 根据角度变化刻度
     * @param trueAngle
     */
    public void changeAngle(final float trueAngle) {
        if (isRunning){//如果在动直接返回
            return;
        }
        final Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                switch (state) {
                    case 1://后退状态
                        isRunning=true;
                        targetAngle -= 3;
                        if (targetAngle <= 0) {//如果回退到0
                            targetAngle = 0;
                            //改为前进状态
                            state = 2;
                        }
                        break;
                    case 2://前进状态
                        targetAngle += 3;
                        if (targetAngle >= trueAngle) {//如果增加到指定角度
                            targetAngle = trueAngle;
                            //改为后退状态
                            state = 1;
                            isRunning=false;
                            //结束本次运动
                            timer.cancel();
                        }
                        break;
                    default:
                        break;
                }
                //重新绘制(子线程中使用的方法)
                postInvalidate();
            }
        }, 500, 30);
    }


    private OnAngleColorListener onAngleColorListener;

    public void setOnAngleColorListener(OnAngleColorListener onAngleColorListener) {
        this.onAngleColorListener = onAngleColorListener;
    }

    public interface OnAngleColorListener{
        void colorListener(int red,int green);
    }

}

MainActivity

package com.weiyu.sharedanimator;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {


    private DivisionCircleView divisionCircleView;
    private LinearLayout ll_parent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ll_parent = (LinearLayout) findViewById(R.id.ll);
        divisionCircleView = (DivisionCircleView) findViewById(R.id.dcv);
        divisionCircleView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                divisionCircleView.changeAngle(200);
            }
        }); //设置角度颜色变化监听
        divisionCircleView.setOnAngleColorListener(new DivisionCircleView.OnAngleColorListener() {
            @Override
            public void colorListener(int red, int green) {
                Color color=new Color();
                //通过Color对象将RGB值转为int类型
                int backColor= color.argb(100,red,green,0);
                //父布局设置背景
                ll_parent.setBackgroundColor(backColor);
            }
        });

    }

}

xml


<LinearLayout
    android:id="@+id/ll"
    android:gravity="center"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.weiyu.sharedanimator.DivisionCircleView
        android:id="@+id/dcv"
        android:layout_width="300dp"
        android:layout_height="200dp"/>
LinearLayout>

先发一下,随后再编辑,我会仔细封装,尽量帮大家理清思路
安卓自定义刻度盘控件_第3张图片

你可能感兴趣的:(android)