先贴效果图
图中的小圆点是可以随着手指的滑动, 绕着绿色的圆移动的哦
这个demo只是实现了部分功能, 但是手指跟随圆移动的逻辑很好玩..
贴代码:
public class CycleView extends View {
private int mMaxProcess = 30;
private int mCurrentProcess = 5;
private static final double RADIAN = 180 / Math.PI;
private Context mContext;
private Paint mBigCyclePaint;
private Paint mMiddleCyclePaint;
private Paint mSmallCyclePaint;
private double mCurrentAngle;
private int mBigCycleradius = 400;
private float mWheelCurX, mWheelCurY;
private CurrentProcessListener mCurrentProcessListener;
public void setmCurrentProcessListener(CurrentProcessListener mCurrentProcessListener) {
this.mCurrentProcessListener = mCurrentProcessListener;
}
interface CurrentProcessListener {
void current(int current);
}
public CycleView(Context context) {
this(context, null);
}
public CycleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CycleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
/**
* 初始化
*
* @param context
* @param attrs
*/
private void init(Context context, AttributeSet attrs) {
this.mContext = context;
mBigCyclePaint = new Paint();
mBigCyclePaint.setColor(Color.GREEN);
mBigCyclePaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mBigCyclePaint.setStyle(Paint.Style.STROKE);
mBigCyclePaint.setStrokeWidth(10);
mMiddleCyclePaint = new Paint();
mMiddleCyclePaint.setColor(Color.BLUE);
mMiddleCyclePaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mMiddleCyclePaint.setStyle(Paint.Style.STROKE);
mMiddleCyclePaint.setStrokeWidth(10);
mSmallCyclePaint = new Paint();
mSmallCyclePaint.setColor(Color.RED);
mSmallCyclePaint.setFlags(Paint.ANTI_ALIAS_FLAG);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
canvas.drawCircle(width / 2, height / 2, mBigCycleradius, mBigCyclePaint);
canvas.drawCircle(width / 2 + 80, height / 2 + 80, 260, mMiddleCyclePaint);
canvas.drawCircle(mWheelCurX, mWheelCurY, 60, mSmallCyclePaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
float cos = computeCos(x, y);
//1, 算出点击的度数
if (x < getWidth() / 2) { // 滑动超过180度
mCurrentAngle = Math.PI * RADIAN + Math.acos(cos) * RADIAN;
} else { // 没有超过180度
mCurrentAngle = Math.PI * RADIAN - Math.acos(cos) * RADIAN;
}
//有了角度,
refershWheelCurPosition(cos);//重装小圆点的位置
if (mCurrentProcessListener != null) {
//把当前的角度改了,
//开始的角度, 应该是135°
double angle = 0;
if (mCurrentAngle < 135) {
angle = mCurrentAngle + (360-135);
} else {
angle = mCurrentAngle - 135;
}
mCurrentProcess = (int) (angle / 360 * mMaxProcess);
mCurrentProcessListener.current(mCurrentProcess);
}
invalidate();
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
private void refershWheelCurPosition(double cos) {
mWheelCurX = calcXLocationInWheel(mCurrentAngle, cos);
mWheelCurY = calcYLocationInWheel(cos);
}
private float calcXLocationInWheel(double angle, double cos) {
if (angle < 180) {
return (float) (getMeasuredWidth() / 2 + Math.sqrt(1 - cos * cos) * mBigCycleradius);
} else {
return (float) (getMeasuredWidth() / 2 - Math.sqrt(1 - cos * cos) * mBigCycleradius);
}
}
private float calcYLocationInWheel(double cos) {
return getMeasuredHeight() / 2 + mBigCycleradius * (float) cos;
}
/**
* 拿到倾斜的cos值
*/
private float computeCos(float x, float y) {
float width = x - getWidth() / 2;
float height = y - getHeight() / 2;
float slope = (float) Math.sqrt(width * width + height * height);
return height / slope;
}
}