做一個智能風扇時 客戶有一個智能遙控器的需求往产,就寫了個比較簡單的自定義控件呵萨。代碼注釋很詳細了,就不多說了伶丐。自己看下啦悼做,有問題的問題一起交流下。
效果如下圖:
/**
* Created by zxd on 2016/6/27.
*/
public class DiskMenuViewEight extends View {
//內(nèi)圓邊框的寬度
private float innerCircleWidth = 10;
//外圍圓的邊框的寬度
private float outerCircleWidth = 15;
//畫筆對象
private Paint mPaint;
//圓心的X坐標
private float centerX;
//圓心的Y坐標
private float centerY;
//內(nèi)圓半徑的顏色
private int outerCircleColor = 0xFFD8D9D9;
//外圍半徑的顏色 哗魂、點擊的顏色
private int innerCircleColor = 0xFFF1F1F1;
//37°正弦值
private float mSin45 = (float) Math.sin(45 * Math.PI / 180);
//37°的余弦值
private float mCos45 = (float) Math.cos(45 * Math.PI / 180);
private float outerCircleRadius, innerCircleRadius;
private AREA mArea;
public DiskMenuViewEight(Context context) {
super(context);
init();
}
//長度
int mWidth;
//高度
int mHeight;
public void setWidthAndHeight(int w, int h) {
this.mWidth = w;
this.mHeight = h;
}
public DiskMenuViewEight(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int w = mWidth;
int h = mHeight;
centerX = w / 2;
centerY = h / 2;
outerCircleRadius = centerX - outerCircleWidth;
innerCircleRadius = centerX / 3;
}
private void init() {
mPaint = new Paint();
}
//定義接口
public interface ChangeStateListener {
void onChangeState(AREA area);
}
ChangeStateListener mChangeStateListener = null;
public void setChangeStateListener(ChangeStateListener changeStateListener) {
mChangeStateListener = changeStateListener;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setAntiAlias(true);
//畫圓
drawCircle(canvas);
//花直線
drawLine(canvas);
//畫背景選擇器
drawOnclikColor(canvas, mArea);
//畫文字
drawText(canvas);
//畫圖
drawImageView1(canvas);
drawImageView2(canvas);
//畫燈泡
drawImageViewCenter(canvas);
}
//畫圖
private void drawImageView1(Canvas canvas) {
Paint imgPaint = new Paint();
imgPaint.setAntiAlias(true);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.reversal);
Matrix matrix = new Matrix();
matrix.postScale(0.3f, 0.3f);
Bitmap dstbmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
RectF mRectF = new RectF((float) (centerX - (mSin45 * outerCircleRadius) / 3 - UiUtil.Dp2Px(20)), (float) (centerY + (0.55f * outerCircleRadius) - UiUtil.Dp2Px(10)),
(float) ((centerX - (mSin45 * outerCircleRadius) / 3) + UiUtil.Dp2Px(20)), (float) (centerY + (0.55f * outerCircleRadius) + UiUtil.Dp2Px(30)));
canvas.drawBitmap(dstbmp, null, mRectF, imgPaint);
}
//畫圖
private void drawImageView2(Canvas canvas) {
Paint imgPaint = new Paint();
imgPaint.setAntiAlias(true);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.wind_speed);
Matrix matrix = new Matrix();
matrix.postScale(0.3f, 0.3f);
Bitmap dstbmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
RectF mRectF = new RectF((float) (centerX + (mSin45 * outerCircleRadius) / 3 - UiUtil.Dp2Px(20)), (float) (centerY + (0.55f * outerCircleRadius) - UiUtil.Dp2Px(10)),
(float) ((centerX + (mSin45 * outerCircleRadius) / 3) + UiUtil.Dp2Px(20)), (float) (centerY + (0.55f * outerCircleRadius) + UiUtil.Dp2Px(30)));
canvas.drawBitmap(dstbmp, null, mRectF, imgPaint);
}
//畫圖
private void drawImageViewCenter(Canvas canvas) {
Paint imgPaint = new Paint();
imgPaint.setAntiAlias(true);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.off_light);
Matrix matrix = new Matrix();
matrix.postScale(0.4f, 0.4f);
Bitmap dstbmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
RectF mRectF = new RectF((float) (centerX - UiUtil.Dp2Px(30)), (float) (centerY - UiUtil.Dp2Px(30)),
(float) (centerX + UiUtil.Dp2Px(30)), (float) (centerY + UiUtil.Dp2Px(30)));
canvas.drawBitmap(dstbmp, null, mRectF, imgPaint);
}
//寫文字
private void drawText(Canvas canvas) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(100);
paint.setColor(innerCircleColor);
paint.setTextAlign(Paint.Align.CENTER);
//寫1
canvas.drawText("1", centerX - mSin45 * (outerCircleRadius / 2) - (outerCircleRadius - innerCircleRadius) * 2 / 5,
centerY + mSin45 * (outerCircleRadius / 2) - (outerCircleRadius - innerCircleRadius) / 20, paint);
//寫2
canvas.drawText("2", centerX - mSin45 * (outerCircleRadius / 2) - (outerCircleRadius - innerCircleRadius) * 2 / 5,
centerY - mCos45 * (outerCircleRadius / 4), paint);
//寫3
canvas.drawText("3", centerX - (mSin45 * outerCircleRadius) / 3, centerY - (0.55f * outerCircleRadius), paint);
//寫4
canvas.drawText("4", centerX + mSin45 * (outerCircleRadius / 3),
centerY - (0.55f * outerCircleRadius), paint);
//寫5
canvas.drawText("5", centerX + mSin45 * (outerCircleRadius / 2) + (outerCircleRadius - innerCircleRadius) * 2 / 5,
centerY - mCos45 * (outerCircleRadius / 4), paint);
//寫6
canvas.drawText("6", centerX + mSin45 * (outerCircleRadius / 2) + (outerCircleRadius - innerCircleRadius) * 2 / 5,
centerY + mSin45 * (outerCircleRadius / 2) - (outerCircleRadius - innerCircleRadius) / 20, paint);
}
//畫圓
private void drawCircle(Canvas canvas) {
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(centerX, centerY, outerCircleRadius, mPaint);
mPaint.setColor(outerCircleColor);
mPaint.setStrokeWidth(outerCircleWidth);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(centerX, centerY, outerCircleRadius, mPaint);
mPaint.setColor(outerCircleColor);
mPaint.setStrokeWidth(10);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(centerX, centerY, innerCircleRadius, mPaint);
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(centerX, centerY, innerCircleRadius, mPaint);
}
//畫直線
private void drawLine(Canvas canvas) {
mPaint.setColor(outerCircleColor);
mPaint.setStrokeWidth(5);
//第一條
canvas.drawLine(centerX, centerY - innerCircleRadius, centerX, centerY - outerCircleRadius, mPaint);
//第二條
canvas.drawLine(centerX - (mSin45 * outerCircleRadius), centerY - (mSin45 * outerCircleRadius),
centerX - (mSin45 * innerCircleRadius), centerY - (mSin45 * innerCircleRadius), mPaint);
//第三條
canvas.drawLine(centerX - innerCircleRadius, centerY, centerX - outerCircleRadius, centerY, mPaint);
//第四條
canvas.drawLine(centerX - (mSin45 * outerCircleRadius), centerY + (mSin45 * outerCircleRadius),
centerX - (mSin45 * innerCircleRadius), centerY + (mSin45 * innerCircleRadius), mPaint);
//第五條
canvas.drawLine(centerX - (mSin45 * outerCircleRadius), centerY + (mSin45 * outerCircleRadius),
centerX - (mSin45 * innerCircleRadius), centerY + (mSin45 * innerCircleRadius), mPaint);
//第六條
canvas.drawLine(centerX, centerY + innerCircleRadius, centerX, centerY + outerCircleRadius, mPaint);
//第七條
canvas.drawLine(centerX + (mSin45 * outerCircleRadius), centerY + (mSin45 * outerCircleRadius),
centerX + (mSin45 * innerCircleRadius), centerY + (mSin45 * innerCircleRadius), mPaint);
//第八條
canvas.drawLine(centerX + innerCircleRadius, centerY, centerX + outerCircleRadius, centerY, mPaint);
//第九條
canvas.drawLine(centerX + (mSin45 * outerCircleRadius), centerY - (mSin45 * outerCircleRadius),
centerX + (mSin45 * innerCircleRadius), centerY - (mSin45 * innerCircleRadius), mPaint);
}
/**
* 清空畫布
*
* @param canvas
*/
private void clearCanvas(Canvas canvas) {
canvas.drawColor(Color.WHITE);
}
//按下時的X肛走,Y坐標
float mDownX, mDownY;
//松開時的X,Y坐標
float mUpX, mUpY;
//觸摸事件 即點擊事件的處理
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = event.getX();
mDownY = event.getY();
Log.i("custom", "mDown==" + mDownX);
Log.i("custom", "mDown==" + judgeArea(mDownX, mDownY));
mArea = judgeArea(mDownX, mDownY);
invalidate();
mChangeStateListener.onChangeState(mArea);
break;
case MotionEvent.ACTION_UP:
// clearCanvas(mCanvas);
mArea = null;
invalidate();
break;
default:
break;
}
return true;
}
//判斷區(qū)域
public AREA judgeArea(float x, float y) {
//判斷是是否在大圓內(nèi)
if ((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY) <= outerCircleRadius * outerCircleRadius) {
//判斷是否在小圓內(nèi)
if ((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY) > innerCircleRadius * innerCircleRadius) {
x = x - centerX;
y = y - centerY;
float tan = y / x;
if (tan > Math.tan(45 * Math.PI / 180) && tan < Integer.MAX_VALUE && x < 0 && y < 0) {
return AREA.NUMBER_ONE;
} else if (tan > 0 && tan < Math.tan(45 * Math.PI / 180) && x < 0 && y < 0) {
return AREA.NUMBER_TWO;
} else if (tan < 0 && tan > -Math.tan(45 * Math.PI / 180) && x < 0 && y > 0) {
return AREA.NUMBER_THREE;
} else if (tan < -Math.tan(45 * Math.PI / 180) && tan > Integer.MIN_VALUE && x < 0 && y > 0) {
return AREA.NUMBER_FOUR;
} else if (tan > Math.tan(45 * Math.PI / 180) && tan < Integer.MAX_VALUE && x > 0 && y > 0) {
return AREA.NUMBER_FIVE;
} else if (tan > 0 && tan < Math.tan(45 * Math.PI / 180) && x > 0 && y > 0) {
return AREA.NUMBER_SIX;
} else if (tan > -Math.tan(45 * Math.PI / 180) && tan < 0 && x > 0 && y < 0) {
return AREA.NUMBER_SEVEN;
} else if (tan > Integer.MIN_VALUE && tan < -Math.tan(45 * Math.PI / 180) && x > 0 && y < 0) {
return AREA.NUMBER_EIGHT;
}
} else {
return AREA.CENTER;
}
} else {
return null;
}
return null;
}
/**
* 點擊的時候繪制深色的扇形
*
* @param canvas
* @param area
*/
private void drawOnclikColor(Canvas canvas, AREA area) {
//先訣條件
if (area == null) {
return;
}
//設(shè)置點擊之后的顏色
mPaint.setColor(outerCircleColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(outerCircleRadius - innerCircleRadius);
switch (area) {
case NUMBER_ONE:
canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
+ (outerCircleRadius - innerCircleRadius) + innerCircleWidth), 225, 45, false, mPaint);
break;
case NUMBER_TWO:
canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
+ (outerCircleRadius - innerCircleRadius) + innerCircleWidth), 180, 45, false, mPaint);
break;
case NUMBER_THREE:
canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
+ (outerCircleRadius - innerCircleRadius) + innerCircleWidth), 135, 45, false, mPaint);
break;
case NUMBER_FOUR:
canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
+ (outerCircleRadius - innerCircleRadius) + innerCircleWidth), 90, 45, false, mPaint);
break;
case NUMBER_FIVE:
canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
+ (outerCircleRadius - innerCircleRadius) + innerCircleWidth), 45, 45, false, mPaint);
break;
case NUMBER_SIX:
canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
+ (outerCircleRadius - innerCircleRadius) + innerCircleWidth), 0, 45, false, mPaint);
break;
case NUMBER_SEVEN:
canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
+ (outerCircleRadius - innerCircleRadius) + innerCircleWidth), -45, 45, false, mPaint);
break;
case NUMBER_EIGHT:
canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
+ (outerCircleRadius - innerCircleRadius) + innerCircleWidth), -90, 45, false, mPaint);
break;
case CENTER:
mPaint.setStrokeWidth(0);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(centerX, centerY, innerCircleRadius, mPaint);
break;
default:
break;
}
}
/**
* 關(guān)于不同區(qū)域的枚舉,逆時針方向
*/
public enum AREA {
//第一區(qū)域
NUMBER_ONE,
//第二區(qū)域
NUMBER_TWO,
//第三區(qū)域
NUMBER_THREE,
//第四區(qū)域
NUMBER_FOUR,
//第五區(qū)域
NUMBER_FIVE,
//第六區(qū)域
NUMBER_SIX,
//第七區(qū)域
NUMBER_SEVEN,
//第八區(qū)域
NUMBER_EIGHT,
//中心區(qū)域
CENTER,
}
}