項(xiàng)目地址LargeTurntableApp
public class BigTurntableView extends View {
private int bigTurntableView_bgColor = Color.parseColor("#ffff00");//轉(zhuǎn)盤背景色
private int bigTurntableView_selectRegionColor = Color.parseColor("#330000ff");//選中區(qū)域顏色
private int bigTurntableView_lineColor = Color.parseColor("#ff0000");//分割線的顏色
private int bigTurntableView_lineStrokeWidth = 2;//分割線的寬度
private int bigTurntableView_arrowLineColor = Color.parseColor("#0000ff");//箭頭線的顏色
private int bigTurntableView_textSize = 50;//文字的字體大小
private int bigTurntableView_textColor = Color.parseColor("#ff0000");//文字的顏色
private String bigTurntableView_content = "";//aa|bb|cc 傳入轉(zhuǎn)盤文字?jǐn)?shù)據(jù)
private Paint mPaint;
private Scroller mScroller;
private VelocityTracker mVelocityTracker;
private boolean isShowSelected = false;//是否展示選中的
private boolean isUseTouchEvent = true;//觸摸事件是否有效 默認(rèn)有效
private float avgDegree;//平均角度大小 根據(jù)內(nèi)容自動(dòng)計(jì)算
private float rotateDegree;//旋轉(zhuǎn)角度 默認(rèn)第一條數(shù)據(jù)會(huì)在上方
private String[] bisectionContent;//數(shù)據(jù)數(shù)組
private volatile int contentIndex = 0;//當(dāng)前選中內(nèi)容下標(biāo)
public BigTurntableView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public void init(Context context, @Nullable AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BigTurntableView);
bigTurntableView_bgColor = typedArray.getColor(R.styleable.BigTurntableView_bigTurntableView_bgColor, bigTurntableView_bgColor);
bigTurntableView_selectRegionColor = typedArray.getColor(R.styleable.BigTurntableView_bigTurntableView_selectRegionColor, bigTurntableView_selectRegionColor);
bigTurntableView_lineColor = typedArray.getColor(R.styleable.BigTurntableView_bigTurntableView_lineColor, bigTurntableView_lineColor);
bigTurntableView_lineStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.BigTurntableView_bigTurntableView_lineStrokeWidth, bigTurntableView_lineStrokeWidth);
bigTurntableView_arrowLineColor = typedArray.getColor(R.styleable.BigTurntableView_bigTurntableView_arrowLineColor, bigTurntableView_arrowLineColor);
bigTurntableView_textSize = typedArray.getDimensionPixelSize(R.styleable.BigTurntableView_bigTurntableView_textSize, bigTurntableView_textSize);
bigTurntableView_textColor = typedArray.getColor(R.styleable.BigTurntableView_bigTurntableView_textColor, bigTurntableView_textColor);
bigTurntableView_content = typedArray.getString(R.styleable.BigTurntableView_bigTurntableView_content);
if (TextUtils.isEmpty(bigTurntableView_content)) {
bigTurntableView_content = "0|1|2|3|4|5";
}
bisectionContent = bigTurntableView_content.split("\\|");
avgDegree = 360 / bisectionContent.length;
rotateDegree = -avgDegree / 2;//默認(rèn)選擇角度
mScroller = new Scroller(getContext(), new AccelerateDecelerateInterpolator());
mPaint = new Paint();
typedArray.recycle();
}
private int measuredWidth;
private int measuredHeight;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
measuredWidth = getMeasuredWidth();
measuredHeight = getMeasuredHeight();
}
@Override
protected void onDraw(Canvas canvas) {
int cX = measuredWidth / 2;
int cY = measuredHeight / 2;
int cR = measuredHeight / 2;
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));//抗鋸齒
mPaint.setAntiAlias(true);//抗鋸齒
mPaint.setStyle(Paint.Style.FILL);
canvas.save();
mPaint.setColor(bigTurntableView_bgColor);
canvas.drawCircle(cX, cY, cR, mPaint);//畫背景色
canvas.restore();
canvas.save();
float selectBeginDegree;
int offsetIndex = 0;
if (rotateDegree <= 0) {
offsetIndex = (int) -(Math.abs(rotateDegree) / avgDegree);
contentIndex = (int) (Math.abs(rotateDegree) / avgDegree) % bisectionContent.length;
} else {
offsetIndex = (int) (Math.abs(rotateDegree) / avgDegree) + 1;
contentIndex = (int) (Math.abs(rotateDegree) / avgDegree) % bisectionContent.length + 1;
contentIndex = bisectionContent.length - contentIndex;
}
selectBeginDegree = rotateDegree - avgDegree * offsetIndex - avgDegree * bisectionContent.length / 4;
if (isShowSelected) {
mPaint.setColor(bigTurntableView_selectRegionColor);
Path mPath = new Path();
RectF rectF = new RectF(cX - cR, cY - cR, cX + cR, cY + cR);
mPath.addArc(rectF, selectBeginDegree, avgDegree);
mPath.lineTo(cX, cY);
mPath.close();
canvas.drawPath(mPath, mPaint);//畫選中的扇形區(qū)域顏色
}
mPaint.setStrokeWidth(bigTurntableView_lineStrokeWidth);
mPaint.setColor(bigTurntableView_lineColor);
canvas.rotate(rotateDegree, cX, cY);
for (int i = 0; i < bisectionContent.length; i++) {
if (avgDegree == 360)
break;
canvas.drawLine(cX, 0, cX, cY, mPaint);//畫區(qū)域線
canvas.rotate(avgDegree, cX, cY);
}
canvas.rotate(avgDegree / 2, cX, cY);
mPaint.setColor(bigTurntableView_textColor);
for (int i = 0; i < bisectionContent.length; i++) {
if (avgDegree == 360)
break;
mPaint.setTextSize(bigTurntableView_textSize);
canvas.drawText(bisectionContent[i], cX - bisectionContent[i].length() * bigTurntableView_textSize / 2, cY / 2, mPaint);//畫文字
canvas.rotate(avgDegree, cX, cY);
}
canvas.restore();
canvas.save();
mPaint.setColor(bigTurntableView_arrowLineColor);
mPaint.setStrokeWidth(bigTurntableView_lineStrokeWidth * 2);
canvas.drawLine(cX, 0, cX, cY, mPaint);
canvas.drawLine(cX, 0, cX - 25, 25, mPaint);
canvas.drawLine(cX, 0, cX + 25, 25, mPaint);//畫箭頭
canvas.restore();
}
private float lastX = 0f;
private float lastY = 0f;
private float disX, disY;
private boolean isAllowShowSelected = false;//初始化時(shí)不允許展示選中
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isUseTouchEvent)
return super.onTouchEvent(event);
float viewX = event.getX();
float viewY = event.getY();
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
isAllowShowSelected = true;
mScroller.forceFinished(true);
addVelocityTracker(event);
lastX = viewX;
lastY = viewY;
break;
case MotionEvent.ACTION_MOVE:
hideSelected();
isAllowShowSelected = false;
addVelocityTracker(event);
disX = viewX - lastX;
disY = viewY - lastY;
lastX = viewX;
lastY = viewY;
rotateDegree = (int) (rotateDegree + disY);
invalidate();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// 在觸點(diǎn)抬起后再繼續(xù)滑動(dòng)一定距離
int xVelocity = getXScrollVelocity();
int yVelocity = getYScrollVelocity();
mScroller.fling(0, lastScrollCurrY, (int) (xVelocity), (int) (yVelocity), -Integer.MIN_VALUE, Integer.MAX_VALUE, -Integer.MIN_VALUE, Integer.MAX_VALUE);
invalidate();
recycleVelocityTracker();
break;
}
return true;
}
private int lastScrollCurrY = 0;
private int computeScrollDistance = 0;
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
computeScrollDistance = mScroller.getCurrY() - lastScrollCurrY;
lastScrollCurrY = mScroller.getCurrY();
rotateDegree = (int) (rotateDegree + computeScrollDistance);
if (mScroller.isFinished()) {
isShowSelected = true;
isAllowShowSelected = true;
}
if (!isAllowShowSelected) {
invalidate();
}
}
if (isAllowShowSelected) {
showSelected();
if (onSelectedListener != null) {
onSelectedListener.onSelected(Math.abs(contentIndex), getBisectionContent());
}
isAllowShowSelected = false;
}
}
/**
* 添加用戶的速度跟蹤器
*/
private void addVelocityTracker(MotionEvent event) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
}
/**
* 移除用戶速度跟蹤器
*/
private void recycleVelocityTracker() {
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
/**
* 獲取X方向的滑動(dòng)速度,大于0向右滑動(dòng),反之向左
*/
private int getXScrollVelocity() {
mVelocityTracker.computeCurrentVelocity(500);
int velocity = (int) mVelocityTracker.getXVelocity();
return velocity;
}
/**
* 獲取Y方向的滑動(dòng)速度,大于0向下滑動(dòng),反之向上
*/
private int getYScrollVelocity() {
mVelocityTracker.computeCurrentVelocity(500);
int velocity = (int) mVelocityTracker.getYVelocity();
return velocity;
}
private void showSelected() {
isShowSelected = true;
invalidate();
}
private void hideSelected() {
isShowSelected = false;
invalidate();
}
//自動(dòng)選擇一次
public void startAutoSelect(OnSelectedListener onSelectedListener) {
this.onSelectedListener = onSelectedListener;
post(new Runnable() {
@Override
public void run() {
hideSelected();
int dis = (int) ((Math.random()) * 1000 + 1000);
mScroller.startScroll(0, lastScrollCurrY, 0, dis, 1000 * 3);
invalidate();
}
});
}
public void setBigTurntableView_bgColor(int bigTurntableView_bgColor) {
this.bigTurntableView_bgColor = bigTurntableView_bgColor;
invalidate();
}
public void setBigTurntableView_selectRegionColor(int bigTurntableView_selectRegionColor) {
this.bigTurntableView_selectRegionColor = bigTurntableView_selectRegionColor;
invalidate();
}
public void setBigTurntableView_lineColor(int bigTurntableView_lineColor) {
this.bigTurntableView_lineColor = bigTurntableView_lineColor;
invalidate();
}
public void setBigTurntableView_lineStrokeWidth(int bigTurntableView_lineStrokeWidth) {
this.bigTurntableView_lineStrokeWidth = bigTurntableView_lineStrokeWidth;
}
public void setBigTurntableView_arrowLineColor(int bigTurntableView_arrowLineColor) {
this.bigTurntableView_arrowLineColor = bigTurntableView_arrowLineColor;
invalidate();
}
public void setBigTurntableView_textSize(int bigTurntableView_textSize) {
this.bigTurntableView_textSize = bigTurntableView_textSize;
invalidate();
}
public void setBigTurntableView_textColor(int bigTurntableView_textColor) {
this.bigTurntableView_textColor = bigTurntableView_textColor;
invalidate();
}
public void setBigTurntableView_content(String bigTurntableView_content) {
this.bigTurntableView_content = bigTurntableView_content;
invalidate();
}
//設(shè)置觸摸事件是否有效
public void setUseTouchEvent(boolean useTouchEvent) {
isUseTouchEvent = useTouchEvent;
}
public String[] getBisectionContent() {
return bisectionContent;
}
private OnSelectedListener onSelectedListener;
public interface OnSelectedListener {
void onSelected(int posion, String[] bisectionContent);
}
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--大轉(zhuǎn)盤-->
<declare-styleable name="BigTurntableView">
<attr name="bigTurntableView_bgColor" format="color" /><!--轉(zhuǎn)盤背景色-->
<attr name="bigTurntableView_selectRegionColor" format="color" /><!--選中區(qū)域顏色-->
<attr name="bigTurntableView_lineColor" format="color" /><!--分割線的顏色-->
<attr name="bigTurntableView_lineStrokeWidth" format="dimension" /><!--分割線的寬度-->
<attr name="bigTurntableView_arrowLineColor" format="color" /><!--箭頭線的顏色-->
<attr name="bigTurntableView_textSize" format="dimension" /><!--文字的字體大小-->
<attr name="bigTurntableView_textColor" format="color" /><!--文字的顏色-->
<attr name="bigTurntableView_content" format="string" /><!--aa|bb|cc 傳入轉(zhuǎn)盤文字?jǐn)?shù)據(jù)-->
</declare-styleable>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.dxh.myapplication.widget.BigTurntableView
android:id="@+id/bigTurntableView"
android:layout_width="wrap_content"
android:layout_height="400dp"
app:bigTurntableView_arrowLineColor="#0000ff"
app:bigTurntableView_bgColor="#00ff00"
app:bigTurntableView_content="面|餅|湯菜|米飯|混沌|餃子|減肥|睡覺(jué)"
app:bigTurntableView_lineColor="#ff0000"
app:bigTurntableView_lineStrokeWidth="2px"
app:bigTurntableView_selectRegionColor="#330000ff"
app:bigTurntableView_textColor="#ff0000"
app:bigTurntableView_textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_autoSelect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="自動(dòng)選擇一次"
app:layout_constraintTop_toBottomOf="@+id/bigTurntableView" />
</androidx.constraintlayout.widget.ConstraintLayout>
bigTurntableView.setUseTouchEvent(false);//設(shè)置觸摸事件是否有效
btnAutoSelect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//開(kāi)啟自動(dòng)選擇
bigTurntableView.startAutoSelect(new BigTurntableView.OnSelectedListener() {
@Override
public void onSelected(int posion, String[] bisectionContent) {
Toast.makeText(MainActivity.this, bisectionContent[posion], Toast.LENGTH_SHORT).show();
}
});
}
});
效果圖

1.gif