记录下之前开发ui效果。
public class RoundScaleView2 extends View {
private static final String TAG = "RoundScaleView2";
private Context mContext;
/**
* 画笔对象的引用
*/
private Paint paint;
/**
* 圆环的宽度
*/
private float roundWidth;
/**
* 最大进度
*/
private int max;
/**
* 当前进度
*/
private int progress = 0;
private int progress2 = 0;
private boolean lightType = false;
public static final int LIGHTID = 66;
private int last_y = -1;
private int last_y2 = -1;
private int numberOfPointers = 1;
String[] paintColors = {
"#FF0000", "#FF2525", "#FF9C00", "#FFEF00", "#CBFF00", "#7BFF00", "#00FF37", "#02E863", "#00D35E", "#00C45C", "#00D795", "#00C1FF"
,"#0082FF", "#0050FF", "#0032FF", "#0000FF", "#2814FF", "#4E00FF", "#6A10FF", "#BD0EFF", "#FF00E3", "#FF2288", "#FF1666", "#FF0039"
,"#E60000", "#FF0000", "#FF0000", "#FF0000", "#FF0000", "#FF0000", "#FF0000", "#FF0000", "#FF0000", "#FF0000", "#FF0000", "#FF0000"
};
// 调整后颜色值
int[] colors = {
0xFF0000, 0xFF0500, 0xFF5000, 0xC8C800, 0x82FF00, 0x64FF00, 0x46FF00, 0x1EFF00, 0x28C800, 0x146400, 0x14DC05, 0x00A00F
,0x14641E, 0x003232, 0x003296, 0x0032E6, 0x0000FF, 0x1E00FF, 0x3C00FF, 0x6400FF, 0x960064, 0xC8001E, 0xEB000A, 0xFF0005
,0xE60000, 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000
};
int[] progress_rate = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
,12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
,24, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1};
private PointF mProgressPoint;
private PointF mProgressPoint2;
private Boolean isEnabled = true;
public RoundScaleView2(Context context) {
this(context, null);
}
public RoundScaleView2(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundScaleView2(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
paint = new Paint();
//获取自定义属性和默认值
roundWidth = dip2px(context,9);
//最大刻度
max = 36;
//外边距
paddingOuterThumb = dip2px(mContext,10);
}
@Override
public void onDraw(Canvas canvas) {
/**
* 圆环颜色
*/
paint.setStrokeWidth(roundWidth); //设置圆环的宽度
paint.setColor(getResources().getColor(R.color.transparent)); //设置进度的颜色
// paint.setColor(getResources().getColor(R.color.light_effectt_red));
RectF oval2 = new RectF(centerX - radius , centerY - radius , centerX + radius , centerY +
radius); //用于定义的圆弧的形状和大小的界限
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true); //消除锯齿
canvas.drawArc(oval2, 270, 360, false, paint); //根据进度画圆弧
// 画Thumb
canvas.save();
//画可拖动的圆点
if (isLightType()){
drawTouchBar(canvas);
}
}
/**
* 画可拖动的圆点
* @param canvas
*/
private void drawTouchBar(Canvas canvas) {
mProgressPoint = calcArcEndPointXY(centerX, centerY, radius + 30, 360 *
progress / max, (float) 150.5);
// //直接用画笔画
paint.setColor(Color.parseColor(getPaintColors()));
canvas.drawCircle(mProgressPoint.x, mProgressPoint.y,1,paint);
// canvas.rotate(getTouchBarOffset(),progressPoint.x, progressPoint.y);
// canvas.drawRect(progressPoint.x, progressPoint.y,progressPoint.x, progressPoint.y,paint);
canvas.restore();
canvas.save();
mProgressPoint2 = calcArcEndPointXY(centerX, centerY, radius + 30, 360 *
progress2 / max, (float) 150.5);
// //直接用画笔画
paint.setColor(Color.parseColor(getPaintColors2()));
canvas.drawCircle(mProgressPoint2.x, mProgressPoint2.y,1,paint);
canvas.restore();
}
public String getPaintColors() {
String color = "#000000";
HashMap<Integer, Object> map = new HashMap<>();
for (int i = 0; i < paintColors.length; i++) {
map.put(progress_rate[i], paintColors[i]);
}
if (map.size() >0) {
for (int i = 0; i < map.size(); i++) {
if (progress == progress_rate[i]) {
color = paintColors[i];
}
}
}
if (!isEnabled){
color = "#00000000";
}
return color;
}
public String getPaintColors2() {
String color = "#000000";
HashMap<Integer, Object> map = new HashMap<>();
for (int i = 0; i < paintColors.length; i++) {
map.put(progress_rate[i], paintColors[i]);
}
if (map.size() >0) {
for (int i = 0; i < map.size(); i++) {
if (progress2 == progress_rate[i]) {
color = paintColors[i];
}
}
}
if (getNumberOfPointers() == 1){
color = "#00000000";
}
return color;
}
private boolean downOnArc = false;
private int downOnPointNum = 0;
public void setViewEnabled(boolean enabled) {
isEnabled = enabled;
if (isEnabled){
setAlpha(1f);
}else {
setAlpha(0.4f);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled){
return false;
}
int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (isLightType()&&isTouchArc(x, y)) {
downOnArc = true;
if (isPointerOne(x,y) && downOnPointNum == 0){
updateArc(x, y,1);
downOnPointNum = 1;
}
if (!isPointerOne(x,y) && downOnPointNum == 0){
updateArc(x, y,2);
downOnPointNum = 2;
}
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (isLightType()&&downOnArc) {
if (downOnPointNum == 1){
updateArc(x, y,1);
}else {
updateArc(x, y,2);
}
setUpVibration();
final ViewParent parent = getParent();
if (parent != null) {
//通知父控件不要拦截事件
parent.requestDisallowInterceptTouchEvent(true);
}
return true;
}
break;
case MotionEvent.ACTION_UP:
downOnArc = false;
downOnPointNum = 0;
if (progress2 == progress){
if (progress2 == 24){
progress2 = progress - 1;
}else {
progress2 = progress + 1;
}
}
invalidate();
if (isLightType()&&changeListener != null) {
changeListener.onProgressChangeEnd(max, progress,progress2);
if (!valueInTheDarkArea(progress)){
// 调用振动
LightEffectUtils.performKeyPressHapticFeedback(getContext(),this);
}
}
break;
}
return super.onTouchEvent(event);
}
private void setUpVibration() {
if (last_y != getProgress() && !valueInTheDarkArea(getProgress())){
for (int i = 0; i <progress_rate.length ; i++) {
if (getProgress() == progress_rate[i]){
// 调用振动
LightEffectUtils.performKeyPressHapticFeedback(getContext(),this);
last_y = getProgress();
}
}
}
if (last_y2 != getProgress2() && !valueInTheDarkArea(getProgress2())){
for (int i = 0; i <progress_rate.length ; i++) {
if (getProgress2() == progress_rate[i]){
// 调用振动
LightEffectUtils.performKeyPressHapticFeedback(getContext(),this);
last_y2 = getProgress2();
}
}
}
}
private int centerX, centerY;
private int radius;
private int paddingOuterThumb;
@Override
protected void onSizeChanged(int width, int height, int oldw, int oldh) {
centerX = width / 2;
centerY = height / 2;
int minCenter = Math.min(centerX, centerY);
radius = (int) (minCenter - roundWidth / 2 - paddingOuterThumb); //圆环的半径
minValidateTouchArcRadius = (int) (radius - paddingOuterThumb * 1.5f);
maxValidateTouchArcRadius = (int) (radius + paddingOuterThumb * 1.5f);
super.onSizeChanged(width, height, oldw, oldh);
}
// 根据点的位置,更新进度
private void updateArc(int x, int y,int downOnPointNum) {
// 当前移动或者点击位置
int cx = x - getWidth() / 2;
int cy = y - getHeight() / 2;
// 计算角度,得出(-1->1)之间的数据,等同于(-180°->180°)
double angle = Math.atan2(cy, cx) / Math.PI;
// 将角度转换成(0->2)之间的值,然后减去145°的偏移量
angle = ((2 + angle) % 2 - (145 / 180f)) % 2;
// 用(0->2)之间的角度值乘以总进度,等于当前进度
// 当前变化进度
int i = (int) (angle * max / 2);
int adjustProgress = progressFormatConversion(i);
if (isLeftDarkArea(adjustProgress)){
adjustProgress = 0;
}else if (isRightDarkArea(adjustProgress)){
adjustProgress = 24;
}
if (downOnPointNum == 1){
progress = adjustProgress;
}else if(downOnPointNum == 2){
progress2 = adjustProgress;
}
if (changeListener != null) {
changeListener.onProgressChange(max, progress,progress2);
}
invalidate();
}
private int progressFormatConversion(int num){
switch (num){
case -14:
num = 22;
break;
case -13:
num = 23;
break;
case -12:
num = 24;
break;
}
return num;
}
// 判断是指针1
private boolean isPointerOne(int x, int y){
// 当前移动或者点击位置
int cx = x - getWidth() / 2;
int cy = y - getHeight() / 2;
// 计算角度,得出(-1->1)之间的数据,等同于(-180°->180°)
double angle = Math.atan2(cy, cx) / Math.PI;
// 将角度转换成(0->2)之间的值,然后减去145°的偏移量
angle = ((2 + angle) % 2 - (145 / 180f)) % 2;
// 用(0->2)之间的角度值乘以总进度,等于当前进度
// 当前变化进度
int i = (int) (angle * max / 2);
int adjustProgress = progressFormatConversion(i);
if (isLeftDarkArea(adjustProgress)){
adjustProgress = 0;
}else if (isRightDarkArea(adjustProgress)){
adjustProgress = 24;
}
if (getNumberOfPointers() != 1){
int abs1 = Math.abs(adjustProgress - progress);
int abs2 = Math.abs(adjustProgress - progress2);
if (abs1 > abs2){
return false;
}else {
return true;
}
}else {
return true;
}
}
private int minValidateTouchArcRadius; // 最小有效点击半径
private int maxValidateTouchArcRadius; // 最大有效点击半径
// 判断是否按在圆边上
private boolean isTouchArc(int x, int y) {
double d = getTouchRadius(x, y);
if (d >= minValidateTouchArcRadius && d <= maxValidateTouchArcRadius) {
return true;
}
return false;
}
// 计算某点到圆点的距离
private double getTouchRadius(int x, int y) {
int cx = x - getWidth() / 2;
int cy = y - getHeight() / 2;
return Math.hypot(cx, cy);
}
public synchronized int getMax() {
return max;
}
/**
* 设置进度的最大值
*
* @param max
*/
public synchronized void setMax(int max) {
if (max < 0) {
throw new IllegalArgumentException("max not less than 0");
}
this.max = max;
}
/**
* 获取指针数量
*
* @return
*/
public int getNumberOfPointers() {
return numberOfPointers;
}
/**
* 设置指针数量
*
* @return
*/
public void setNumberOfPointers(int numberOfPointers) {
this.numberOfPointers = numberOfPointers;
}
/**
* 获取进度.需要同步
*
* @return
*/
public synchronized int getProgress() {
return progress;
}
/**
* 获取进度.需要同步
*
* @return
*/
public synchronized int getProgress2() {
return progress2;
}
/**
* 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步
* 刷新界面调用postInvalidate()能在非UI线程刷新
*
* @param mProgress
*/
public synchronized void setProgress(int mProgress) {
if (mProgress < 0) {
throw new IllegalArgumentException("progress not less than 0");
}
if (mProgress > max) {
progress = max;
}
if (mProgress <= max) {
this.progress = mProgress;
postInvalidate();
}
}
/**
* 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步
* 刷新界面调用postInvalidate()能在非UI线程刷新
*
* @param mProgress2
*/
public synchronized void setProgress2(int mProgress2) {
if (mProgress2 < 0) {
throw new IllegalArgumentException("progress2 not less than 0");
}
if (mProgress2 > max) {
progress2 = max;
}
if (mProgress2 <= max) {
if (mProgress2 == progress){
if (progress2 == 24){
progress2 = progress - 1;
}else {
progress2 = progress + 1;
}
}else {
this.progress2 = mProgress2;
}
postInvalidate();
}
}
public void setViewColorfulType(int type){
if (type == 2){
if (progress2 == progress){
if (progress2 == 24){
progress2 = progress - 1;
}else {
progress2 = progress + 1;
}
}else {
progress2 = 0;
}
setNumberOfPointers(2);
}else {
progress2 = progress;
setNumberOfPointers(1);
}
postInvalidate();
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 是否是黑暗不可点击区域
* @param mProgress
* @return
*/
public static boolean valueInTheDarkArea(int mProgress){
int[] progress = {-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1 };
for (int i = 0; i < progress.length; i++) {
if (mProgress == progress[i]){
return true;
}
}
return false;
}
/**
* 是否是左区域
* @param mProgress
* @return
*/
public static boolean isLeftDarkArea(int mProgress){
int [] progress = {-5,-4,-3,-2,-1};
for (int i = 0; i < progress.length; i++) {
if (mProgress == progress[i]){
return true;
}
}
return false;
}
/**
* 是否是左区域
* @param mProgress
* @return
*/
public static boolean isRightDarkArea(int mProgress){
int[] progress = {-11,-10,-9,-8,-7,-6};
for (int i = 0; i < progress.length; i++) {
if (mProgress == progress[i]){
return true;
}
}
return false;
}
/**
* 依圆心坐标,半径,扇形角度,计算出扇形终射线与圆弧交叉点的xy坐标
*
* @param cirX 圆centerX
* @param cirY 圆centerY
* @param radius 圆半径
* @param cirAngle 当前弧角度
* @param orginAngle 起点弧角度
* @return 扇形终射线与圆弧交叉点的xy坐标
*/
public static PointF calcArcEndPointXY(float cirX, float cirY, float radius, float
cirAngle, float orginAngle) {
cirAngle = (orginAngle + cirAngle) % 360;
return calcArcEndPointXYForDoom(cirX, cirY, radius, cirAngle);
}
/**
* For Doom
* 依圆心坐标,半径,扇形角度,计算出扇形终射线与圆弧交叉点的xy坐标
*
* @param cirX 圆centerX
* @param cirY 圆centerY
* @param radius 圆半径
* @param cirAngle 当前弧角度
* @return 扇形终射线与圆弧交叉点的xy坐标
*/
public static PointF calcArcEndPointXYForDoom(float cirX, float cirY, float radius, float
cirAngle) {
float posX = 0.0f;
float posY = 0.0f;
float arcAngle = 0.0f;
//将角度转换为弧度
if (cirAngle<90&&cirAngle>28) {
arcAngle = (float) (Math.PI * 28.0 / 180.0);
}else {
arcAngle = (float) (Math.PI * cirAngle / 180.0);
}
if (cirAngle < 90) {
posX = cirX + (float) (Math.cos(arcAngle)) * radius;
posY = cirY + (float) (Math.sin(arcAngle)) * radius;
} else if (cirAngle == 90) {
posX = cirX;
posY = cirY + radius;
} else if (cirAngle > 90 && cirAngle < 180) {
if(cirAngle>90&&cirAngle<150.5){
arcAngle = (float) (Math.PI * (180 - 150.5) / 180.0);
}else{
arcAngle = (float) (Math.PI * (180 - cirAngle) / 180.0);
}
posX = cirX - (float) (Math.cos(arcAngle)) * radius;
posY = cirY + (float) (Math.sin(arcAngle)) * radius;
} else if (cirAngle == 180) {
posX = cirX - radius;
posY = cirY;
} else if (cirAngle > 180 && cirAngle < 270) {
arcAngle = (float) (Math.PI * (cirAngle - 180) / 180.0);
posX = cirX - (float) (Math.cos(arcAngle)) * radius;
posY = cirY - (float) (Math.sin(arcAngle)) * radius;
} else if (cirAngle == 270) {
posX = cirX;
posY = cirY - radius;
} else {
arcAngle = (float) (Math.PI * (360 - cirAngle) / 180.0);
posX = cirX + (float) (Math.cos(arcAngle)) * radius;
posY = cirY - (float) (Math.sin(arcAngle)) * radius;
}
return new PointF(posX, posY);
}
private OnProgressChangeListener changeListener;
public void setChangeListener(OnProgressChangeListener changeListener) {
this.changeListener = changeListener;
}
public interface OnProgressChangeListener {
void onProgressChange(int duration, int progress ,int progress2);
void onProgressChangeEnd(int duration, int progress ,int progress2);
}
public boolean isLightType() {
return lightType;
}
public void setLightType(boolean lightType) {
this.lightType = lightType;
}
}