package com.tws.app.myapplication.view;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.tws.app.myapplication.R;
public class SliderBar extends View {
//画背景的Paint
private Paint mBgPaint;
//画进度条的Paint
private Paint mProgressPaint;
//开始位置
private int mStart;
private int mProEnd;
private int mWidth;
private int mHeight;
//结束位置
private int mEnd;
//渐变颜色 三个
private int mStartColor;
private int mEndColor;
//背景颜色
private int mBgColor;
//当前进度
private float mProgress;
//小圆点半径
private int mRadius;
//显示文字的Rect
private Rect mTxtRec;
//最里面白色圆的半径
private int mMinRadio;
//线中心距离上方距离
private int mTop;
//文字距离线的距离
private int mTextTop;
private float mMaxSun;
private float mMinSun;
private Paint mSunPaint;
private Canvas mLeftSunCanvas = new Canvas();
private Canvas mLeftTopSunCanvas = new Canvas();
private Canvas mLeftDownSunCanvas = new Canvas();
private Canvas mTopSunCanvas = new Canvas();
private Canvas mRightTopSunCanvas = new Canvas();
private Canvas mRightSunCanvas = new Canvas();
private Canvas mRightDownCanvas = new Canvas();
private Canvas mDownCanvas = new Canvas();
//进度条改变回调
private ProgressChange progressChange;
private LinearGradient mLinearGradient;
public SliderBar(Context context) {
this(context, null);
}
public SliderBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public SliderBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public SliderBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initPaint();
initParams(context, attrs, defStyleAttr);
}
private void initPaint() {
mBgPaint = new Paint();
mBgPaint.setAntiAlias(true);
mBgPaint.setStrokeCap(Paint.Cap.SQUARE);
mProgressPaint = new Paint();
mProgressPaint.setAntiAlias(true);
mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
mSunPaint = new Paint();
mSunPaint.setAntiAlias(true);
mSunPaint.setStrokeCap(Paint.Cap.ROUND);
mSunPaint.setStrokeWidth(8);
}
/***
* 初始化公共参数
*/
public void initParams(Context context, AttributeSet attrs, int defStyleAttr) {
TypedArray seekArray = context.obtainStyledAttributes(attrs, R.styleable.SliderBar, defStyleAttr, 0);
mStartColor = seekArray.getColor(R.styleable.SliderBar_startColor, ContextCompat.getColor(context, R.color.startColor));
mEndColor = seekArray.getColor(R.styleable.SliderBar_endColor, ContextCompat.getColor(context, R.color.endColor));
mBgColor = seekArray.getColor(R.styleable.SliderBar_bgColor, ContextCompat.getColor(context, R.color.bgColor));
mRadius = (int) seekArray.getDimension(R.styleable.SliderBar_radius, dp2px(8));
mMinRadio = (int) seekArray.getDimension(R.styleable.SliderBar_minRadio, dp2px(40));
mTxtRec = new Rect();
mMaxSun = (float) (mRadius * 0.6f / 1.7);
mMinSun = (float) (mRadius * 0.4f / 1.7);
mSunPaint.setColor(ContextCompat.getColor(context, R.color.white));
seekArray.recycle();
}
private float dp2px(int input) {
float scale = Resources.getSystem().getDisplayMetrics().density;
return (float) ((input / scale) + 0.5);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//初始化高和宽
initWidthAndHeight(w, h);
}
protected void initWidthAndHeight(int w, int h) {
mStart = getPaddingStart();
mTop = getPaddingTop();
mEnd = getMeasuredWidth() - getPaddingRight();
mWidth = mEnd - mStart;
mHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
mLinearGradient = new LinearGradient(0, 0, w, h
, new int[]{mStartColor, mEndColor}
, new float[]{0, 1F}
, Shader.TileMode.CLAMP);
mBgPaint.setStrokeWidth((float) mHeight);
mProgressPaint.setStrokeWidth((float) mHeight);
}
public interface ProgressChange {
void onProgressChange(float progress);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawBg(canvas);
drawProgress(canvas);
drawSun(canvas);
}
/**
* set progres
*
* @param mProgress progress
*/
public void setProgress(float mProgress) {
this.mProgress = mProgress;
invalidate();
}
private void drawBg(Canvas canvas) {
mBgPaint.setColor(mBgColor);
canvas.drawRoundRect(mStart + 1, mTop, mEnd - 1, mHeight, mRadius, mRadius, mBgPaint);
}
private void drawProgress(Canvas canvas) {
mProgressPaint.setShader(mLinearGradient);
mProEnd = (int) ((mProgress) * (mEnd - mStart)) + mStart;
if (mProEnd <= mRadius * 2) {
mProEnd = mRadius * 2;
}
canvas.drawRoundRect(mStart, mTop, mProEnd, mHeight, mRadius, mRadius, mProgressPaint);
}
private void drawSun(Canvas canvas) {
float scale = mProgress * (mMaxSun - mMinSun) + mMinSun;
int alpha = (int) (255 * (mProgress * 0.2f + 0.8f));
canvas.drawCircle((mStart + mRadius), (mStart + mRadius), scale, mSunPaint);
float lightLength = scale * 0.3F;
float lightOffset = scale * 1.7F;
float mLightStartX = mStart + mRadius;
int mLightStartY = mTop + mRadius;
canvas.save();
for (int i = 0; i < 8; i++) {
float radians = (float) Math.toRadians(i * 45);
float offsetX = (float) (lightOffset * Math.cos(radians));
float offsetY = (float) (lightOffset * Math.sin(radians));
float x1, x2, y1, y2;
x1 = mLightStartX + offsetX;
x2 = (float) (x1 + lightLength * Math.cos(radians));
y1 = mLightStartY + offsetY;
y2 = (float) (y1 + lightLength * Math.sin(radians));
mSunPaint.setAlpha(alpha);
canvas.drawLine(x1, y1, x2, y2, mSunPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
getProgress(event);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
getRootView().performClick();
invalidate();
break;
}
return true;
}
/***
* 计算进度
*/
private void getProgress(MotionEvent event) {
mProgress = event.getX() / (mWidth - mRadius);
if (mProgress < 0) {
mProgress = 0;
}
if (mProgress > 1) {
mProgress = 1;
}
if (progressChange != null) {
progressChange.onProgressChange(mProgress);
}
invalidate();
}
/**
* set progress listener
*
* @param progressChange progress listener
*/
public void setProgressChange(ProgressChange progressChange) {
this.progressChange = progressChange;
}
}