andriod自定义slider

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;

    }

}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容