android自定义可拖拽的仪表盘
程序员文章站
2022-03-10 16:58:14
本文实例为大家分享了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了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: MySQL 数据类型选择原则
下一篇: 浅谈如何提高PHP代码质量之单元测试