效果和蓝舞者app播放界面调节播放速率类似效果如下:
主要代码如下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//最底层方块
oval =new RectF(0,0,
getWidth() -vernierRadius, getWidth() -vernierRadius);
//y的最小值
if (miny ==0) {
miny = zhigaodianY((int) (oval.right /2));
invalidate();
}
//最上层方块
RectF oval1 =new RectF(borderWith,borderWith - (oval.right /2) - (miny -oval.right /2) -vernierRadius,
oval.right -borderWith,oval.right - (borderWith + (oval.right /2) + (miny -oval.right /2) +vernierRadius));
Path path =new Path();
path.setFillType(Path.FillType.INVERSE_WINDING);
path.addArc(oval1,30,120);
maxX = zhigaodianX((int) (oval.right /2),BIG_ZHIGAODIAN);
//draw lift arc
canvas.save();
canvas.clipPath(path, Region.Op.REPLACE);
canvas.translate(0, -(oval.right /2 + (miny -oval.right /2) +vernierRadius));
//startAngle 起始点角度 下午3点位置为0度 sweepAngle 共多少角度 useCenter是否是扇形
canvas.drawArc(oval,30,120,isActs,backPaint);
canvas.restore();
canvas.save();
//
canvas.clipPath(path, Region.Op.REPLACE);
canvas.translate(0, -(oval.right /2 + (miny -oval.right /2) +vernierRadius));
if (seekX !=0 &&touchNum !=0) {
if (seekX >oval.right /2) {
canvas.drawArc(oval,startAngle, -90 +sweepAngle,isActs,rightPaint);
}else {
canvas.drawArc(oval,startAngle,sweepAngle -90,isActs,liftPaint);
}
}
canvas.restore();
if (seekX ==0) {
seekY =oval.right;
seekX =oval.right /2;
}
if (seekX >oval.right /2) {
paint.setColor(rightColor);
}else {
paint.setColor(liftColor);
}
canvas.save();
canvas.translate(0, -(oval.right /2 + (miny -oval.right /2) +vernierRadius));
canvas.drawCircle(seekX,seekY,vernierRadius,paint);
canvas.restore();
}
touch中
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_UP:
return true;
case MotionEvent.ACTION_MOVE:
int radius = (int)oval.right /2;//半径
seekX = event.getX();
//超出View边界 设置不拦截事件全部停止
if (seekX >oval.right ||seekX <0)
return false;
//根据公式 (x - x0) * (x - x0) + (y - y0) * (y - y0) = r * r
seekY = huxian(radius);
setActProgress(radius);
touchNum++;
invalidate();
return true;
}
return super.onTouchEvent(event);
}
setActProgres方法
float atan = (float) (Math.atan2(seekY - radius,seekX - radius));
sweepAngle = (float) (180 * atan / Math.PI);
if (onMoveListener !=null) {
double lenght =maxX -minX;//进度条总长度
//每1是多少
schedule = lenght /totalProgress;
double v = (seekX +minX) /schedule;
onMoveListener.onMoveListener((float) v -38);
}
huxian方法中
float y = (float) (Math.sqrt(Math.pow(radius,2) - Math.pow(seekX - radius,2)) + radius);
float y1 = zhigaodianY(radius);
if (y1 +15 > y) {
seekX = ((float) zhigaodianX(radius,seekX > radius ?BIG_ZHIGAODIAN :SMALL_ZHIGAODIAN));
return y1 +15;
}
return y;
zhigaodianY方法
maxY = (float) ((float) radius + (radius * Math.sin(210)));
return maxY;
zhigaodianX方法
if (flag ==BIG_ZHIGAODIAN) {
// if (maxX != -1)
// return maxX;
maxX = radius + radius * Math.cos(flag) + zhigaodianX(radius,SMALL_ZHIGAODIAN);
return maxX;
}
// if (minX != -1)
// return minX;
minX = radius * Math.cos(flag) +5;
return minX;
所有属性
private int liftColor;
private int rightColor;
private int progress;
private int atProgress;
private final int DEVIATION =60;//左右角度
private Paintpaint;
private float seekX =0;
private float seekY =0;
private int width;
private int height;
private int vernierRadius =20;//这是滑动游标的半径
private PaintbackPaint =new Paint();//背景圆弧画笔
private PaintliftPaint =new Paint();//左侧滑动选中画笔
private PaintrightPaint =new Paint();//右侧滑动选中画笔
private PaintsldingPaint =new Paint();//滑块画笔
private int backColor;
private int sldingColor;
private float backRadus;//背景圆弧的半径
private RectFoval;
private final int BIG_ZHIGAODIAN = -150;//x轴最大坐标
private final int SMALL_ZHIGAODIAN =30;//x轴最小坐标
private final float startAngle =90;//进度起始角度
private float sweepAngle =0;//进度总角度角度
private int borderWith =10;
OnMoveListeneronMoveListener;
private float totalProgress =200;
private double maxX = -1;
private double minX = -1;
private float maxY = -1;
private double schedule;
private boolean isActs =false;//是否绘制进度扇形
private float miny;
private int touchNum =0;//事件次数
这里面需要用到的公式
根据x坐标判断y坐标的位置
公式:x * x + y * y = r * r 来源于勾股定理原理
根据x,y坐标确定角度
公式:360 / 2 * arctan(y / x) / π
基本主要公式在这里了
还有sin和cos的使用,主要用来求出滑块能移动的最小y值和滑块能移动的最大x值和最小x值。
这个View还没有完善,没有时间了,以后有时间在慢慢的完善,可能有些漏洞,有什么问题可以私信我,谢谢。