自定义View之刻度盘

转载请注明出处:http://blog.csdn.net/Myleike/article/details/50776680

很多时候android原生的控件都不能满足我们的需求,比如说我们要实现下面这个内存清理按钮:
![这里写图片描述](https://img-blog.csdn.net/20160302230442994)
这时就需要我们自定义一个控件了。

自定义控件共需完成下面四个步骤:
  • 定义控件属性
  • 在代码中获取属性值
  • 重写onMeasure()方法(不是必须)
  • 重写onDraw()方法
    废话不多说,直接上代码
    一、定义控件属性
    res/values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="DialView">
        <attr name="padding" format="float"/>
        <attr name="out_oval_color" format="color"/>
        <attr name="bar_color" format="color"/>
        <attr name="bar_background_color" format="color"/>
        <attr name="graduation_color" format="color"/>
        <attr name="progress" format="integer"/>
        <attr name="context" format="string"/>
        <attr name="min_size" format="string"/>
        <attr name="max_size" format="string"/>
        <attr name="text_color" format="color"/>
    </declare-styleable>
</resources>

二、在代码中获取属性值

public DialView(Context context, AttributeSet attrs, int defStyle){
        super(context, attrs, defStyle);
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DialView, defStyle, 0);
        padding = typedArray.getFloat(R.styleable.DialView_padding, 10);
        outOvalColor = typedArray.getColor(R.styleable.DialView_out_oval_color, Color.WHITE);
        barColor = typedArray.getColor(R.styleable.DialView_bar_color, Color.WHITE);
        barBackgroundColor = typedArray.getColor(R.styleable.DialView_bar_background_color, 0x60ffffff);
        graduationColor = typedArray.getColor(R.styleable.DialView_graduation_color, Color.WHITE);
        progress = typedArray.getInt(R.styleable.DialView_progress, 0);
        barContext = typedArray.getString(R.styleable.DialView_context);
        minSize = typedArray.getString(R.styleable.DialView_min_size);
        maxSize = typedArray.getString(R.styleable.DialView_max_size);
        textColor = typedArray.getColor(R.styleable.DialView_text_color, Color.WHITE);
    }

三、重写onMeasure()方法计算控件大小

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //计算控件宽度
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        //计算控件高度
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
        this.w = sizeWidth-padding*2;
        this.h = sizeHeight - padding*2;
        this.radius = w / 2 < h / 2 ? w / 2 : h / 2; // 计算半径
        this.center = new Point(sizeWidth/2, sizeHeight/2);//计算圆心

        this.outRadius = radius / 31 * 30.5F;//外圆半径
        this.barRadius = radius / 31 * 28;//进度条半径
        this.inRadius = radius / 31 * 26F;//内圆半径
        initView();
    }

初始化画笔

 private void initView(){
        Paint basePaint = new Paint();
        basePaint.setAntiAlias(true);
        basePaint.setStyle(Paint.Style.STROKE);

        outOvalPaint = new Paint(basePaint);
        outOvalPaint.setColor(outOvalColor);
        outOvalPaint.setStrokeWidth(2);

        barPaint = new Paint(basePaint);
        barPaint.setColor(barColor);
        //设置圆弧为圆端
        barPaint.setStrokeCap(Paint.Cap.ROUND);
        barPaint.setStrokeWidth(radius / 31 * 3);

        graduationPaint = new Paint(basePaint);
        graduationPaint.setColor(graduationColor);
        graduationPaint.setStrokeWidth(2);

        textPaint = new Paint(basePaint);
        textPaint.setColor(textColor);
    }

四、重写onDraw()方法绘制控件

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Point liftStart = CustomViewMath.getPoint(center, outRadius, 315.0);
        Point rightStart = CustomViewMath.getPoint(center, outRadius, 45.0);
        // 绘制外圆弧
        canvas.drawArc(creatRectF(outRadius), 135, 270, false, outOvalPaint);
        //  绘制横线
        canvas.drawLine(liftStart.x, liftStart.y, liftStart.x - 10,
                liftStart.y, outOvalPaint);
        canvas.drawLine(rightStart.x, rightStart.y, rightStart.x + 10,
                rightStart.y, outOvalPaint);
        //绘制进度条
        barPaint.setColor(barColor);
        canvas.drawArc(creatRectF(barRadius), 135, 270 * progress / 100,false,barPaint);
        barPaint.setColor(barBackgroundColor);
        canvas.drawArc(creatRectF(barRadius), 135, 270,false,barPaint);

        // 绘制内圆弧
        canvas.drawArc(creatRectF(inRadius), 135, 270, false, graduationPaint);
        int length;
        for (int i = 0; i < 101; i++) {
            if (i % 10 == 0)
                length = 12;
            else if (i % 5 == 0)
                length = 9;
            else
                length = 5;
            Point start = CustomViewMath.getPoint(center, inRadius, (double) (315 - i * space));
            Point stop = CustomViewMath.getPoint(center, inRadius - length, (double)(315 - i * space));
            canvas.drawLine(start.x, start.y, stop.x, stop.y, graduationPaint);
        }
        /** 绘制百分比 */
        textPaint.setTextSize(radius / 3 * 2);
        float l = textPaint.measureText(progress + "");
        canvas.drawText(progress + "", (getWidth() - l) / 2, getHeight() / 2, textPaint);

        textPaint.setTextSize(radius / 9 * 2);
        canvas.drawText("%", (getWidth() - l) / 2 + l, getHeight() / 2, textPaint);
        /**绘制信息*/
        if(barContext!=null&&!barContext.equals("")){
            textPaint.setTextSize(radius / 13 * 2);
            Paint.FontMetrics fm1 = textPaint.getFontMetrics();
            float tl = textPaint.measureText(barContext);
            canvas.drawText(barContext, (getWidth() - tl) / 2, getHeight() / 2 + (fm1.bottom-fm1.top)*2, textPaint);
        }
        //绘制数值范围
        Point liftPoint = CustomViewMath.getPoint(center, barRadius, 315.0);
        Point rightPoint = CustomViewMath.getPoint(center, barRadius, 45.0);
        textPaint.setTextSize(radius / 15 * 2);
        float minl = textPaint.measureText(minSize);
        float maxl = textPaint.measureText(maxSize);
        canvas.drawText(minSize, liftPoint.x - minl / 2, liftPoint.y + minl / 3
                * 2, textPaint);
        canvas.drawText(maxSize, rightPoint.x - maxl / 2, rightPoint.y + maxl
                / 3 * 2, textPaint);
    }

我们还可以为他添加点击事件——重写onTouchEvent()

 @Override
    public boolean onTouchEvent(MotionEvent event) {
        RectF rectF = creatRectF(radius);
        if(isDown)  return true;
        if (event.getX() > rectF.left && event.getX() < rectF.right && event.getY() > rectF.top && event.getY() < rectF.bottom) {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                isDown = true;
                //这里是一个回掉接口,我们可以通过实现他来做我们的操作
                if (listener != null)
                    listener.onClick();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Random random = new Random();
                        int n = random.nextInt(100)+1;
                        try {
                            while (progress > 0) {
                                progress--;
                                Thread.sleep(20);
                                Message msg = new Message();
                                msg.what = 1;
                                mhandler.sendMessage(msg);
                            }
                            while (progress < n) {
                                progress++;
                                Thread.sleep(20);
                                Message msg = new Message();
                                msg.what = 1;
                                mhandler.sendMessage(msg);
                            }
                            isDown = false;
                        }catch (Exception e){}
                    }
                    }).start();
            }
        }
        return  true;
    }

由于篇幅原因,这里只贴主要代码。要查看源码,请点击下载

转载请注明出处:http://blog.csdn.net/Myleike/article/details/50776680

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值