![](https://img.haomeiwen.com/i1351616/55238313f2a325a2.png)
文本的内容 区域数 起始角度(x轴正向0度 逆时针)可自定
package com.hrg.gys.rebot.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.hrg.hefei.R;
import com.xin.common.utils.LogUtils;
/**
* https://www.jianshu.com/p/207ea78f1634
* Created by zxd on 2016/6/27.
*/
public class DiskMenuView extends View {
ChangeStateListener mChangeStateListener = null;
//按下时的X,Y坐标
private int mArea = -1;
//内圆边框的宽度
private float innerCircleWidth = 10;
//外围圆的边框的宽度
private float outerCircleWidth = 15;
//画笔对象
private Paint paintLine;
private Paint paintText;
private Paint paintClick;
int itemAngle;/*每个格的角度*/
/*共分多少格*/
private int cellNum = 4;
/*开始的角度*/
private int startAngle = 0;
/*显示在中间的文本*/
private String[] strArr;
//圆心的X坐标
private float centerX;
//圆心的Y坐标
private float centerY;
//内圆半径的颜色
private int outerCircleColor = 0xFFD8D9D9;
//外围半径的颜色 、点击的颜色
private int innerCircleColor = 0xFF000000;
private float outerCircleRadius, innerCircleRadius;
public DiskMenuView(Context context) {
this(context, null);
}
public DiskMenuView(Context context, AttributeSet attributeSet) {
this(context, attributeSet, 0);
}
public DiskMenuView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttr(context, attrs);
init();
}
private void initAttr(Context context, AttributeSet attrs) {
TypedArray t = context.obtainStyledAttributes(attrs, R.styleable.DiskMenuView);
cellNum = t.getInt(R.styleable.DiskMenuView_DiskMenuView_CellNum, 4);
startAngle = t.getInt(R.styleable.DiskMenuView_DiskMenuView_StartAngle, 0);
String _strArr = t.getString(R.styleable.DiskMenuView_DiskMenuView_StrArr);
if (_strArr != null && _strArr.split(",").length >= cellNum) {
strArr = _strArr.split(",");
}
t.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int w = getMeasuredWidth();
int h = getMeasuredHeight();
centerX = w / 2;
centerY = h / 2;
outerCircleRadius = Math.min(centerX, centerY) - outerCircleWidth;
innerCircleRadius = outerCircleRadius / 3;
}
private void init() {
paintLine = new Paint();
itemAngle = 360 / cellNum;
paintText = new Paint();
paintText.setAntiAlias(true);
paintText.setTextSize(30);
paintText.setStrokeWidth(20);
paintText.setColor(innerCircleColor);
paintText.setTextAlign(Paint.Align.CENTER);
paintClick = new Paint();
}
public void setChangeStateListener(ChangeStateListener changeStateListener) {
mChangeStateListener = changeStateListener;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paintLine.setAntiAlias(true);
//画圆
drawCircle(canvas);
//花直线
drawLine(canvas);
//画背景选择器
drawOnclikColor(canvas);
//画文字
drawText(canvas);
}
//写文字
private void drawText(Canvas canvas) {
Paint.FontMetricsInt fontMetrics = paintText.getFontMetricsInt();
float centerRadius = (outerCircleRadius + innerCircleRadius) / 2;
// canvas.drawPoints(new float[]{centerX,centerY},paintText);
for (int i = 0; i < cellNum; i++) {
// paintText.setColor(i == 0 ? Color.RED : Color.GREEN);
int _itemStartAngle = itemAngle * i + startAngle;
int _itemEndAngle = _itemStartAngle + itemAngle;
int _averageAngle = (_itemEndAngle + _itemStartAngle) / 2;
float textX = (float) (centerX + Math.cos(_averageAngle * Math.PI / 180) * centerRadius);
float texty = (float) (centerY + Math.sin(_averageAngle * Math.PI / 180) * centerRadius);
// canvas.drawPoints(new float[]{textX,texty},paintText);
/*基线的位置*/
int baseline = (int) (texty - (fontMetrics.bottom + fontMetrics.top) / 2);
String text = strArr != null ? strArr[i + 1] : String.valueOf(i + 1);
canvas.drawText(text, textX, baseline, paintText);
}
int baseline = (int) (centerY - (fontMetrics.bottom + fontMetrics.top) / 2);
String text = strArr != null ? strArr[0] : String.valueOf(0);
canvas.drawText(text, centerX, baseline, paintText);
}
//画圆
private void drawCircle(Canvas canvas) {
paintLine.setColor(Color.WHITE);
paintLine.setStyle(Paint.Style.FILL);
canvas.drawCircle(centerX, centerY, outerCircleRadius, paintLine);
paintLine.setColor(outerCircleColor);
paintLine.setStrokeWidth(outerCircleWidth);
paintLine.setStyle(Paint.Style.STROKE);
canvas.drawCircle(centerX, centerY, outerCircleRadius, paintLine);
paintLine.setColor(outerCircleColor);
paintLine.setStrokeWidth(innerCircleWidth);
paintLine.setStyle(Paint.Style.STROKE);
canvas.drawCircle(centerX, centerY, innerCircleRadius, paintLine);
paintLine.setColor(Color.WHITE);
paintLine.setStyle(Paint.Style.FILL);
canvas.drawCircle(centerX, centerY, innerCircleRadius, paintLine);
}
//画直线
private void drawLine(Canvas canvas) {
paintLine.setColor(outerCircleColor);
paintLine.setStrokeWidth(5);
for (int i = 0; i < cellNum; i++) {
// paintLine.setColor(i == 0 ? Color.RED : Color.GREEN);
double v = (itemAngle * i + startAngle) * Math.PI / 180;
double sinItem = Math.sin(v);
double cosItem = Math.cos(v);
canvas.drawLine((int) (centerX + (cosItem * outerCircleRadius)),
(int) (centerY + (sinItem * outerCircleRadius)),
(int) (centerX + (cosItem * innerCircleRadius)),
(int) (centerY + (sinItem * innerCircleRadius)),
paintLine);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mArea = judgeArea(event.getX(), event.getY());
if (mArea >= 0) {
invalidate();
log("mChangeStateListener->" + mArea);
if (mChangeStateListener != null && mArea >= 0) {
mChangeStateListener.onChangeState(mArea);
}
}
break;
case MotionEvent.ACTION_UP:
if (mArea >= 0) {
mArea = -1;
invalidate();
}
break;
default:
break;
}
return true;
}
//触摸事件 即点击事件的处理
//判断区域
public int judgeArea(float x, float y) {
//判断是是否在大圆内
if ((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY) <= outerCircleRadius * outerCircleRadius) {
//判断是否在小圆内
if ((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY) > innerCircleRadius * innerCircleRadius) {
x = x - centerX;
y = centerY - y;
float tan = y / x;
double angle = 0;
double mathAngle = Math.atan(Math.abs(tan)) * 180 / Math.PI;
if (x >= 0 && y >= 0) { //一象限
angle = mathAngle;
} else if (x <= 0 && y >= 0) { //二角限
angle = 180 - mathAngle;
} else if (x <= 0 && y <= 0) {//三
angle = 180 + mathAngle;
} else if (x >= 0 && y <= 0) { //四
angle = 360 - mathAngle;
}
log("judgeArea->" + angle);
int area = (int) Math.ceil((360 - (angle + startAngle)) / itemAngle);
if (area > cellNum) {
area = area - cellNum;
}
return area;
} else {
return 0;
}
} else {
return -1;
}
}
private void log(String t) {
LogUtils.log("DiskMenuView", t);
}
/**
* 点击的时候绘制深色的扇形
*
* @param canvas
*/
private void drawOnclikColor(Canvas canvas) {
if (mArea == -1) { //未选中
return;
} else if (mArea == 0) { //中心区域
paintClick.setStrokeWidth(0);
paintClick.setStyle(Paint.Style.FILL);
canvas.drawCircle(centerX, centerY, innerCircleRadius, paintClick);
return;
} else {
paintClick.setColor(outerCircleColor);
paintClick.setStyle(Paint.Style.STROKE);
paintClick.setStrokeWidth(outerCircleRadius - innerCircleRadius);
RectF oval = new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
+ (outerCircleRadius - innerCircleRadius) + innerCircleWidth);
canvas.drawArc(oval, (mArea - 1) * itemAngle + startAngle, itemAngle, false, paintClick);
}
}
//定义接口
public interface ChangeStateListener {
/**
* @param area 0 中心点 1是 1号位置 2号位置
*/
void onChangeState(int area);
}
}
//attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DiskMenuView">
<attr name="DiskMenuView_CellNum" format="integer" />
<attr name="DiskMenuView_StartAngle" format="integer" />
<attr name="DiskMenuView_StrArr" format="reference|string" />
</declare-styleable>
</resources>
//layout.xml
<com.hrg.gys.rebot.view.DiskMenuView
android:id="@+id/dmve2"
android:layout_width="match_parent"
app:DiskMenuView_CellNum="4"
app:DiskMenuView_StartAngle="-135"
app:DiskMenuView_StrArr="暂停,前,右,后,左"
android:layout_height="match_parent"
android:layout_margin="@dimen/view_size_20"/>
网友评论