欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

android自定义可拖拽的仪表盘

程序员文章站 2022-03-10 16:58:14
本文实例为大家分享了android自定义可拖拽的仪表盘的具体代码,供大家参考,具体内容如下因为项目最近需要用到仪表盘,又不想使用之前使用的背景图的方式。主要是想自己写一点代码。觉得绘制要比图片好。于是...

本文实例为大家分享了android自定义可拖拽的仪表盘的具体代码,供大家参考,具体内容如下

因为项目最近需要用到仪表盘,又不想使用之前使用的背景图的方式。主要是想自己写一点代码。觉得绘制要比图片好。于是有了下面这张图:

android自定义可拖拽的仪表盘

面从弧度,刻度,文字,指针都是canvas绘制出来的。

/**
 * created by xulc on 2018/7/18.
 */

public class dashboardview extends view {
    private  int minwidthdp = 200;
    private  int minheightdp = 100;

    private paint arcpaint,arcinnerpaint,linepaint,textpaint;
    private int arccolor = color.parsecolor("#0096ff");  //外层弧形颜色
    private int arcinnercolor =  color.parsecolor("#ffffffff");  //内层弧形颜色
    private int linecolor = color.parsecolor("#333333");   //线条颜色
    private int pointercolor = color.parsecolor("#439aff");   //指针颜色

    private int arcwidthdp = 1;

    private rectf arcrectf,arcinnerrectf;

    private int widthdash = 0;//表盘的宽度

    private int mwidth =0;
    private int mheight = 0;

    private float shortlinelength = 0 ,longlinelength = 0;   //线的长度

    private path path = new path();

    private path pointerpath = new path();   //指针绘制路径

    private region pointerregion = new region();  //指针区域

    private rectf rectf = new rectf();

    private boolean ischoosepointer = false;

    private int mdegree = 0;

    public dashboardview(context context) {
        this(context,null);
    }

    public dashboardview(context context, @nullable attributeset attrs) {
        super(context, attrs);
        initpaint();
    }
    //初始化相关资源
    private void initpaint() {
        arcpaint = new paint();
        arcpaint.setcolor(arccolor);
        arcpaint.setantialias(true);
        arcpaint.setstrokecap(paint.cap.square);
        arcpaint.setstrokewidth(1);
        arcpaint.setstyle(paint.style.fill);

        arcinnerpaint = new paint();
        arcinnerpaint.setcolor(arcinnercolor);
        arcinnerpaint.setantialias(true);
        arcinnerpaint.setstrokecap(paint.cap.square);
        arcinnerpaint.setstrokewidth(1);
        arcinnerpaint.setstyle(paint.style.fill);

        linepaint = new paint();
        linepaint.setcolor(linecolor);
        linepaint.setantialias(true);
        linepaint.setstrokecap(paint.cap.square);
        linepaint.setstrokewidth(arcwidthdp);
        linepaint.setstyle(paint.style.fill);

        textpaint = new paint();
        textpaint.setcolor(linecolor);
        textpaint.setantialias(true);
        linepaint.setstrokecap(paint.cap.square);
        linepaint.setstrokewidth(arcwidthdp);
        linepaint.setstyle(paint.style.stroke);
        textpaint.settextalign(paint.align.left);
        textpaint.settextsize(30);

        arcrectf = new rectf();
        arcinnerrectf = new rectf();
    }

    @override
    protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
        int widthmode = measurespec.getmode(widthmeasurespec);
        int heightmode = measurespec.getmode(heightmeasurespec);
        int widthsize = measurespec.getsize(widthmeasurespec);
        int heightsize = measurespec.getsize(heightmeasurespec);

        if(widthsize < densityutil.dip2px(getcontext(),minwidthdp)||heightsize < densityutil.dip2px(getcontext(),minheightdp)){
            widthsize = densityutil.dip2px(getcontext(),minwidthdp);
            heightsize = densityutil.dip2px(getcontext(),minheightdp);
        }

        if(widthsize/2 != heightsize){
            heightsize = widthsize/2;
        }

        setmeasureddimension(widthsize,heightsize + 50);

        arcrectf.left = 0;
        arcrectf.bottom = heightsize*2;
        arcrectf.right = widthsize;
        arcrectf.top = 0;


    }

    @override
    protected void onsizechanged(int w, int h, int oldw, int oldh) {
        super.onsizechanged(w, h, oldw, oldh);
        widthdash = densityutil.dip2px(getcontext(),50);

        arcinnerrectf.left = widthdash;
        arcinnerrectf.bottom = arcrectf.bottom - widthdash;
        arcinnerrectf.right = arcrectf.bottom -widthdash;
        arcinnerrectf.top = widthdash;
        shortlinelength = widthdash/7;
        longlinelength = widthdash/5;
        mwidth = getwidth();
        mheight = getheight() - 50;

        log.d("xulc","mheight----->"+mheight);
        log.d("xulc","arcrectf.bottom----->"+arcrectf.bottom);
    }

    @override
    protected void ondraw(canvas canvas) {
        arcpaint.setcolor(arccolor);
        canvas.drawarc(arcrectf,180,180,true,arcpaint);  //绘制外弧形
        canvas.drawarc(arcinnerrectf,180,180,true,arcinnerpaint);  //绘制内部弧形
        canvas.save();
        drawscale(canvas);  //绘制刻度
        canvas.restore();
        drawtext(canvas);  //绘制文本
        drawpointer(canvas,mdegree);  //绘制指针
    }

    private int mradius = 50;

    //绘制指针
    private void drawpointer(canvas canvas,float degree){
        pointerpath.reset();
        if(ischoosepointer){
            arcpaint.setcolor(pointercolor);
        }
        pointerpath.reset();
        pointerpath.moveto((float)( mwidth/2 - mradius*math.sin(degree/180f*math.pi)),(float)( mheight + mradius*math.cos(degree/180f*math.pi))); //下切点
        pointerpath.lineto(mwidth/2 -  (float) math.cos(degree/180f*math.pi)*(mheight - widthdash - longlinelength -mradius),mheight - (float) math.sin(degree/180f*math.pi)*(mheight - widthdash - longlinelength-mradius));
        pointerpath.lineto((float)( mwidth/2 + mradius*math.sin(degree/180f*math.pi)),(float)( mheight - mradius*math.cos(degree/180f*math.pi)));
        pointerpath.close();
        pointerpath.computebounds(rectf,true);
        pointerregion.setpath(pointerpath,new region((int) rectf.left,(int) rectf.top,(int) rectf.right,(int) rectf.bottom));
        canvas.drawpath(pointerpath,arcpaint);   //path转化为region区域,方便判断用户点击的位置
        path.reset();
        arcpaint.setcolor(arccolor);
        path.addcircle(mwidth/2,mheight,mradius, path.direction.cw);
        canvas.drawpath(path,arcpaint);
        textpaint.settextalign(paint.align.center);
        canvas.drawtext(""+mdegree,mwidth/2,mheight,textpaint);
    }

    //设置度数
    public void setdegree(int degree){
        if(0<=degree && degree<=180){
            mdegree = degree;
            invalidate();
        }
    }

    //触摸事件
    @override
    public boolean ontouchevent(motionevent event) {
        float startx ,starty;
        if(event.getaction()==motionevent.action_down){
            startx = event.getx(); starty = event.gety();
            if(pointerregion.contains((int) startx,(int) starty)){  //在其中
                ischoosepointer =true;
                invalidate();
                return true;   //消费当前事件,否则不会继续分发后续事件
            }
            return false;
        }else if(event.getaction()==motionevent.action_move){
            if(ischoosepointer){
                float x = event.getx(); float y = event.gety();
                if(y <= mheight && x!=mwidth/2){
                    double degree=  math.atan2((mheight-y) ,(mwidth/2 - x));
                    setdegree((int) (degree/math.pi*180));
                }else{
                    if(y > mheight&& x < mwidth/2){  //说明滑到下面了
                        setdegree(0);
                    }else if(y > mheight&& x > mwidth/2){
                        setdegree(180);
                    }
                }
                return true;
            }else{
                return false;
            }

        }else if(event.getaction()==motionevent.action_up||event.getaction()==motionevent.action_cancel){
            ischoosepointer =false;
            invalidate();
            return true;
        }
        return super.ontouchevent(event);
    }


    //绘制文字
    private void drawtext(canvas canvas) {
        textpaint.settextalign(paint.align.left);
        for(int i=0;i<=6;i++){
            int degree = i*30;
            float textwidth = textpaint.measuretext(""+degree);
            if(degree ==0){
                canvas.drawtext("" + degree,mwidth/2 - (float) math.cos(degree/180f*math.pi)*(mheight - widthdash - longlinelength -10) - textwidth/2,mheight - (float) math.sin(degree/180f*math.pi)*(mheight - widthdash - longlinelength-10)+7,textpaint);
            }   //向右边移动7个像素  向下边移动7个像素
            else if(degree == 30){
                    canvas.drawtext("" + degree,mwidth/2 - (float) math.cos(degree/180f*math.pi)*(mheight - widthdash - longlinelength-10) - textwidth/2,mheight - (float) math.sin(degree/180f*math.pi)*(mheight - widthdash - longlinelength-10)+7 ,textpaint);
            }else if(degree ==60){
                canvas.drawtext("" + degree,mwidth/2 - (float) math.cos(degree/180f*math.pi)*(mheight - widthdash - longlinelength-10) - textwidth/2,mheight - (float) math.sin(degree/180f*math.pi)*(mheight - widthdash - longlinelength-10)+7 ,textpaint);
            }else if(degree ==90){
                canvas.drawtext("" + degree,mwidth/2 - (float) math.cos(degree/180f*math.pi)*(mheight - widthdash - longlinelength-10) - textwidth/2,mheight - (float) math.sin(degree/180f*math.pi)*(mheight - widthdash - longlinelength-10)+7 ,textpaint);
            }else{
                canvas.drawtext("" + degree,mwidth/2 - (float) math.cos(degree/180f*math.pi)*(mheight - widthdash - longlinelength - 10) - textwidth,mheight - (float) math.sin(degree/180f*math.pi)*(mheight - widthdash - longlinelength-10)+7 ,textpaint);
            }
        }
    }

    //绘制刻度
    private void drawscale(canvas canvas){
        for(int i=0;i<=36;i++){   //180角度,30度一个长线 0 30 60 90 120 150 180  5条小线   5度一个小线
            if(i%6==0){//长线
                canvas.drawline(widthdash,mheight,widthdash + longlinelength ,mheight,linepaint);
            }else{ //短线
                canvas.drawline(widthdash,mheight,widthdash + shortlinelength ,mheight,linepaint);
            }
            canvas.rotate(5,mwidth/2,mheight);
        }
    }
}

整体代码差不多就这样,代码中详尽的注释。代码基本上都在这了,就不上传git了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

相关标签: android 仪表盘