1. 程式人生 > >Android自定義View圓盤滑動控制元件(已適配多種解析度)

Android自定義View圓盤滑動控制元件(已適配多種解析度)

好久沒寫部落格了,最近在寫一個專案時需要一個可以調節檔位的圓盤, 首先實現這個圓盤自定義View,首先在構造方法中定義畫筆,重寫onDraw(Canvas canvas)方法,進行繪製,首先繪製一個大圓,然後我這個大圓周圍的錶盤顯示一共有9個檔位,為了美觀,每個檔位裡面有8個小指標,這樣一個分為72份,也就是沒5°畫一次,由於我這個還需要有一個設定檔位的按鈕,所以新增檔位的檔位設定。
下面說一下滑動手勢的處理
我們可以在oNMeasure()方法得到該控制元件的大小,除以2就是圓心,我們設定的大圓的半徑為200,用圓心y座標減去200就是0檔位的y座標,通過獲取當前手勢位置,就可以通過這三個點構建三角形,通過初中學的餘弦定理可以求得滑動角度,當滑動到左半部分,角度注意要用360-當前角度。
螢幕適配看了hongyang大神Orz的適配方案,

http://blog.csdn.net/lmj623565791/article/details/45460089

————————–分割線————————————-
上程式碼

package com.example.yasin.dianretan.utils;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import
android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import com.example.yasin.dianretan.R; import java.util.Calendar; /** * Created by Yasin on 2016/4/7. */ public class CirclerView extends View { private int width; private int height; private
Paint mPaintLine; private Paint mPaintCircle; private Paint mPaintSec; private Paint mPaintText,mPaintText2; private int dw;//當前檔位 public static final int NEED_INVALIDATE = 0X23; private double cx,cy;//手勢座標 private double yxx,yxy;//圓心 private String name; private double jd;//滑動的角度 //每隔一秒,在handler中呼叫一次重新繪製方法 private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case NEED_INVALIDATE: invalidate();//告訴UI主執行緒重新繪製 handler.sendEmptyMessageDelayed(NEED_INVALIDATE,1000); break; default: break; } } }; public CirclerView(Context context) { super(context); } public CirclerView(Context context, AttributeSet attrs) { super(context, attrs); /* * 定義多個畫不同東西的畫筆 * */ mPaintLine = new Paint(); mPaintLine.setColor(Color.WHITE); mPaintLine.setStrokeWidth(6); mPaintCircle = new Paint(); mPaintCircle.setColor(context.getResources().getColor(R.color.yellow));//設定顏色 mPaintCircle.setStrokeWidth(10);//設定線寬 mPaintCircle.setAntiAlias(true);//設定是否抗鋸齒 mPaintCircle.setStyle(Paint.Style.STROKE);//設定繪製風格 mPaintText = new Paint(); mPaintText.setColor(Color.WHITE); mPaintText.setStrokeWidth(10); mPaintText.setTextAlign(Paint.Align.CENTER); mPaintText.setTextSize(40); mPaintText2 = new Paint(); mPaintText2.setColor(Color.WHITE); mPaintText2.setStrokeWidth(10); mPaintText2.setTextAlign(Paint.Align.CENTER); mPaintText2.setTextSize(60); //滑針 mPaintSec = new Paint(); mPaintSec.setStrokeWidth(10); mPaintSec.setColor(Color.YELLOW); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); yxx = width/2; yxy = height/2; setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int circleRadius = 200;//大圓半徑 //畫出大圓 canvas.drawCircle(width / 2, height / 2, circleRadius, mPaintCircle); //依次旋轉畫布,畫出每個刻度和對應數字 if(dw==0){ mPaintText2.setColor(Color.RED); canvas.drawText("關",width/2,height/2+60,mPaintText2); }else{ mPaintText2.setColor(Color.WHITE); canvas.drawText(dw+"檔",width/2,height/2+60,mPaintText2); } mPaintText2.setColor(Color.YELLOW); mPaintText2.setTextSize(40); canvas.drawText(name, width / 2, height / 2 - 50, mPaintText2); for (int i = 0; i <= 71; i++) {//一共有72個(刻度+檔位文字) canvas.save();//儲存當前畫布 canvas.rotate(360 / 72 * i, width / 2, height / 2); // canvas.rotate((float)jd, width / 2, height / 2); if(i%8!=0) { if(i<dw*8||i<jd/5.0f){/*如果使用的檔位調節,則該檔位內的都有黃色; 如果滑動的,一個刻度是5°,s所以個當前度數除以5*/ mPaintLine.setColor(Color.YELLOW); }else{ mPaintLine.setColor(Color.WHITE); } canvas.drawLine(width / 2, height / 2 - circleRadius-10, width / 2, height / 2 - circleRadius - 30, mPaintLine); }else { //左起:文字內容,起始位置x座標,起始位置y座標,畫筆 if(i/8<=dw){ mPaintText.setColor(Color.YELLOW); }else{ mPaintText.setColor(Color.WHITE); } canvas.drawText("" + i / 8, width / 2, height / 2 - circleRadius - 20, mPaintText); } canvas.restore(); } float secDegree = (float) jd;//dw/9f*360;//得到指標旋轉的角度 canvas.save(); canvas.rotate(secDegree, width / 2, height / 2); canvas.drawLine(width / 2, height / 2 - circleRadius, width / 2, height / 2 - circleRadius - 30, mPaintSec); canvas.restore(); } public void setDw(int dw){ this.dw = dw; //handler.sendEmptyMessage(NEED_INVALIDATE);//向handler傳送一個訊息,讓它開啟重繪 this.jd = dw*40; invalidate(); } public int getDw(){ return dw; } public void setName(String name){ this.name = name; } public String getName(){ return name; } @Override public boolean onTouchEvent(MotionEvent event) { cx=event.getX(); cy=event.getY(); jd = getJD(cx,cy); if(cx<=yxx) { jd=180+(180-jd); } dw = (int) (jd/40); invalidate(); return true; } /* * type 1表示得到距離,2表示得到的距離的平方 * */ private double getJL(double ax,double ay,double bx,double by,int type){ if(type==1){ return Math.sqrt(((ax-bx)*(ax-bx)+(ay-by)*(ay-by))); }else{ return (((ax-bx)*(ax-bx)+(ay-by)*(ay-by))); } } //計算角度 private double getJD(double ax,double ay){ return (Math.acos(((getJL(ax,ay,yxx,yxy,2)+200*200-getJL(ax,ay,yxx,(yxy-200),2))/(2*200*getJL(ax,ay,yxx,yxy,1))))*180/Math.PI); } }

效果圖
這裡寫圖片描述