android自定義可拖拽的儀表盤
本文實例為大家分享了android自定義可拖拽的儀表盤的具體代碼,供大家參考,具體內(nèi)容如下
因為項目最近需要用到儀表盤,又不想使用之前使用的背景圖的方式。主要是想自己寫一點代碼。覺得繪制要比圖片好。于是有了下面這張圖:
面從弧度,刻度,文字,指針都是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'); //內(nèi)層弧形顏色 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(); //指針區(qū)域 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(); } //初始化相關(guān)資源 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); //繪制內(nèi)部弧形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轉(zhuǎn)化為Region區(qū)域,方便判斷用戶點擊的位置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); } //設(shè)置度數(shù) 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; //消費當(dāng)前事件,否則不會繼續(xù)分發(fā)后續(xù)事件 } 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了。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. .NET SkiaSharp 生成二維碼驗證碼及指定區(qū)域截取方法實現(xiàn)2. 如何在jsp界面中插入圖片3. JSP數(shù)據(jù)交互實現(xiàn)過程解析4. PHP循環(huán)與分支知識點梳理5. XML基本概念XPath、XSLT與XQuery函數(shù)介紹6. AspNetCore&MassTransit Courier實現(xiàn)分布式事務(wù)的詳細過程7. jsp實現(xiàn)登錄界面8. 低版本IE正常運行HTML5+CSS3網(wǎng)站的3種解決方案9. ASP.NET泛型三之使用協(xié)變和逆變實現(xiàn)類型轉(zhuǎn)換10. jsp+servlet簡單實現(xiàn)上傳文件功能(保存目錄改進)
