请标注原文链接地址:https://blog.csdn.net/daxiangzaici/article/details/50470134
pulic class Rota_CircleView extends View {
private Paint paint;
private float a=330f,b=330f;
private float cx=370f,cy=470f;
private float track_radius = 100f; //圆弧半径
private int width;
private double mAngleDeg=0; //角度 相对 startAngle 的 角度
private Bitmap mThumbBitmap;
private double mAngleRad = 1; //当前角度对应的弧度
private double startAngleDeg=30f; //起点与水平方向的夹角
private double totalAngleDeg = 180;
private boolean mEnable = true;
private float mPercent = 0; //百分比
public interface OnCircleViewChangeListener {//圆弧拖动时候回调接口,包括拖动弧度所占百分比,停止拖动时候所占百分比
void onStopTouch(float percent);
void onMoveTouch(float percent);
}
private OnCircleViewChangeListener mOnCircleViewChangeListener;
public void setOnCircleViewChangeListener(OnCircleViewChangeListener l) {
mOnCircleViewChangeListener = l;
}
public Rota_CircleView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public Rota_CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
getAttrs(context, attrs);
}
public Rota_CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
getAttrs(context, attrs);
}
/**
* 得到属性值
*
* @param context
* @param attrs
*/
private void getAttrs(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.Rota_CircleView);
track_radius = ta.getDimension(R.styleable.Rota_CircleView_track_radius, 100f);
int bmp_id = ta.getResourceId(R.styleable.Rota_CircleView_dot_bmp, R.drawable.scrubber_control_normal_holo);
ta.recycle();
mThumbBitmap = BitmapFactory.decodeResource(getResources(), bmp_id);
totalAngleDeg = 180 + 2 * startAngleDeg;
DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics();
Log.i("tzc","track_radius = " + track_radius+", dm.densityDpi = " + dm.densityDpi);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
getParent().requestDisallowInterceptTouchEvent(true);
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!mEnable)
return false;
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
float newx=event.getX();
float newy=event.getY();
pointxy xy = touchToPoint(newx, newy);
cx = xy.x;
cy = xy.y;
if(mOnCircleViewChangeListener != null) {
mOnCircleViewChangeListener.onMoveTouch(mPercent);
}
invalidate();
break;
case MotionEvent.ACTION_UP:
if(mOnCircleViewChangeListener != null) {
mOnCircleViewChangeListener.onStopTouch(mPercent);
}
break;
default:
break;
}
return true;
}
/*
* 由触摸点坐标 获得 相对 startAngle 的角度
*/
private double pointToAngle(float newx, float newy) {
double angle = 0; //角度 相对 startAngle 的 角度
double degrees = 0; //角度
float y = b - newy;
if (x > 0 && y > 0) {
x = newx - a;
y = b - newy;
mAngleRad = Math.atan(x / y);
degrees = mAngleRad*180/Math.PI;
angle = startAngleDeg + 90 + degrees;
} else if (x > 0 && y < 0) {
x = newx - a;
y = newy - b;
mAngleRad = Math.atan(x / y);
degrees = mAngleRad*180/Math.PI;
angle = startAngleDeg + 270 - degrees;
} else if (x < 0 && y < 0) {
x = a - newx;
y = newy - b;
mAngleRad = Math.atan(x / y);
degrees = mAngleRad*180/Math.PI;
angle = startAngleDeg - 90 + degrees;
} else if (x < 0 && y > 0) {
x = a - newx;
y = b - newy;
mAngleRad = Math.atan(x / y);
degrees = mAngleRad*180/Math.PI;
angle = startAngleDeg + 90 - degrees;
}
return angle;
}
private pointxy touchToPoint(float newx, float newy) {
pointxy xy = new pointxy(0, 0);
mAngleDeg = pointToAngle(newx, newy);
mPercent = (float) (mAngleDeg/totalAngleDeg);
Log.i("tzc", "angle1 = " + mAngleDeg );
if(mAngleDeg <=0.0)
mAngleDeg = 360 + mAngleDeg;
if(mAngleDeg >= totalAngleDeg)
mAngleDeg = totalAngleDeg;
Log.i("tzc", "angle2 = " + mAngleDeg );
double x_sin = track_radius * Math.sin(mAngleRad);
double y_cos = track_radius * Math.cos(mAngleRad);
Log.i("tzc", "x_sin = " + x_sin + "y_cos = " + y_cos );
float x = newx - a;
float y = b - newy;
double x_2 = x_sin;
double y_2 = y_cos;
if (x > 0 && y > 0) {
} else if (x > 0 && y < 0) {
y_2 = -1*y_2;
} else if (x < 0 && y < 0) {
x_2 = -1*x_2;
y_2 = -1*y_2;
} else if (x < 0 && y > 0) {
x_2 = -1*x_2;
}
if( isLimit(x_2, y_2)) {
Log.i("tzc", "isLimit");
if(x_2 < 0) {
xy = angleToPoint(0);
} else {
xy = angleToPoint(totalAngleDeg);
}
} else {
if (x > 0 && y > 0) {
xy.x = (float) (a + x_sin);
xy.y = (float) (b - y_cos);
} else if (x > 0 && y < 0) {
xy.x = (float) (a + x_sin);
xy.y = (float) (b + y_cos);
} else if (x < 0 && y < 0) {
xy.x = (float) (a - x_sin);
xy.y = (float) (b + y_cos);
} else if (x < 0 && y > 0) {
xy.x = (float) (a - x_sin);
xy.y = (float) (b - y_cos);
}
}
return xy;
}
private class pointxy{
public float x;
public float y;
pointxy(float x, float y){
this.x = x;
this.y = y;
}
}
private boolean isLimit (double x_sin, double y_cos) {
boolean limit = false;
if(y_cos < 0) {
if(x_sin == 0) {
limit = true;
} else if(x_sin < 0){
if(x_sin > y_cos) {
limit = true;
}
} else {
if(x_sin < -1*y_cos) {
limit = true;
}
}
}
return limit;
}
public void setEnable(boolean enble) {
this.mEnable = enble;
}
private pointxy angleToPoint(double angle) {
pointxy xy = new pointxy(0, 0);
double angdeg1 = angle - startAngleDeg;
double angdeg = Math.abs(angdeg1);
double radians = Math.toRadians(angdeg);
float x = (float) (track_radius * Math.cos(radians));
float y = (float) (track_radius * Math.sin(radians));
if (angdeg1 <= 0f) {
xy.x = (float) (a - x);
xy.y = (float) (b + y);
} else {
xy.x = (float) (a - x);
xy.y = (float) (b - y);
}
return xy;
}
public void setThumbPos(float Percent) {
pointxy xy = new pointxy(0, 0);
mAngleDeg = totalAngleDeg * Percent;
xy = angleToPoint(mAngleDeg);
cx = xy.x;
cy = xy.y;
mPercent = Percent;
if(mOnCircleViewChangeListener != null) {
mOnCircleViewChangeListener.onMoveTouch(mPercent);
}
invalidate();
}
public void setThumbPos(float Percent) {
pointxy xy = new pointxy(0, 0);
mAngleDeg = totalAngleDeg * Percent;
xy = angleToPoint(mAngleDeg);
cx = xy.x;
cy = xy.y;
mPercent = Percent;
if(mOnCircleViewChangeListener != null) {
mOnCircleViewChangeListener.onMoveTouch(mPercent);
}
invalidate();
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
//Log.i("tzc", "onDraw()");
if(mThumbBitmap != null) {
int h = mThumbBitmap.getHeight();
int w = mThumbBitmap.getWidth();
canvas.drawBitmap(mThumbBitmap, cx-w/2, cy-h/2, null);
}
paint = new Paint();
RectF rectF=new RectF(15,10,width-15,width-10);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(22);
paint.setAntiAlias(true);
SweepGradient shader=new SweepGradient(cx, cy, new int[]{0xFFE64506,0xFF1D2BF2,0xFF1D2BF0,Color.GREEN,Color.YELLOW,0xFFE64506,0xFFE64506},
new float[]{0,0.3f,0.5f,0.7f,0.8f,0.9f,1});
paint.setShader(shader);
canvas.drawArc(rectF, 150,(float)mAngleDeg,false, paint);
}
public void set_value(int value){
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
a = width/2;
b = width/2;
//Log.i("tzc", "onMeasure()");
//cx=(float) (a-track_radius*Math.sin(radians));
//cy=(float) (b+track_radius*Math.cos(radians));
//invalidate();
}
}