Android自定义水平拖动条(SetpSeekBar)

如图所示:拖动进度条,松开时离哪个刻度进,就自动滑到临近的刻度位置

 

 

  1、自定义属性 res->values下创建attrs.xml文件

<declare-styleable name="EasySeekBar">
        <attr name="configuration" format="string"/>
        <attr name="progress_bg_color" format="color"/>
        <attr name="progress_color" format="color"/>
        <attr name="circle_r" format="dimension"/>
        <attr name="line" format="dimension"/>
        <attr name="circle_color" format="color"/>
        <attr name="max_progress" format="integer"/>
        <attr name="min_progress" format="integer"/>
        <attr name="progress_with" format="integer"/>
    </declare-styleable>

2、自定义View

package com.example.customseekbar.easy;


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.example.customseekbar.R;

public class StepSeekBar extends View {
    private Context context;

    private String TAG = "StepSeekBar";
    private Paint bgPaint;//seekbar背景
    private Paint progressPaint;//进度
    private Paint circlePaint;//控制小球
    private Point centrePoint;//中心坐标
    private Point WHPoint; //条形的长宽
    private float progress = 0; //进度
    private int value ;//值

    private int space = 20;//刻度线与进度条的距离

    private Paint linePaint;//竖线
    private int lineColor = Color.parseColor("#DFB578"); //DFB578  D81B60


    private String configuration = "horizontal";//形状 vertical、horizontal、circle、semicircle
    private int bgColor;//背景颜色
    private int progressColor;//进度颜色
    private int circleR;//控制小球半径
    private int line;//规格
    private int maxProgress;//最大值
    private int minProgress;//最小值
    private int circleColor;//小球颜色
    private int strokeWidth;

    private boolean isTure;
    private EasySeekBarLister easySeekBarLister;
    public StepSeekBar(Context context) {
        super(context);
        this.context = context;
        init(null);
    }

    public void setEasySeekBarLister(EasySeekBarLister easySeekBarLister) {
        this.easySeekBarLister = easySeekBarLister;
    }

    public StepSeekBar(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init(attrs);
    }

    public StepSeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        initAttrs(attrs);
        initPaint();
    }

    private void initAttrs(AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.EasySeekBar);
        try {
            configuration = typedArray.getString(R.styleable.EasySeekBar_configuration);
            bgColor = typedArray.getColor(R.styleable.EasySeekBar_progress_bg_color, Color.parseColor("#999999"));
            progressColor = typedArray.getColor(R.styleable.EasySeekBar_progress_color,Color.parseColor("#ffffff"));
            circleR = typedArray.getDimensionPixelOffset(R.styleable.EasySeekBar_circle_r,40);
            line = typedArray.getDimensionPixelOffset(R.styleable.EasySeekBar_line,400);
            maxProgress = typedArray.getInt(R.styleable.EasySeekBar_max_progress,100);
            minProgress = typedArray.getInt(R.styleable.EasySeekBar_min_progress,0);
            circleColor = typedArray.getColor(R.styleable.EasySeekBar_circle_color,Color.parseColor("#ffffff"));
            strokeWidth = typedArray.getInt(R.styleable.EasySeekBar_progress_with,12);
        }finally {
            typedArray.recycle();
        }

        centrePoint = new Point();
        WHPoint = new Point();
        if (circleR<strokeWidth/2){
            centrePoint.x = line+strokeWidth/2;
            centrePoint.y = line+strokeWidth/2;

            WHPoint.x = line+strokeWidth;
            WHPoint.y = strokeWidth;
        }else {
            centrePoint.x = line+circleR;
            centrePoint.y = line+circleR;

            WHPoint.x = line+2*circleR;
            WHPoint.y = 2*circleR;
        }
        setValue(minProgress);
    }

    private void initPaint() {
        //初始低画笔
        bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bgPaint.setAntiAlias(true);
        bgPaint.setColor(bgColor);
        bgPaint.setStrokeWidth(strokeWidth-2);
        bgPaint.setStrokeCap(Paint.Cap.ROUND);

        //初始进度画笔
        progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        progressPaint.setAntiAlias(true);
        progressPaint.setColor(progressColor);
        progressPaint.setStrokeCap(Paint.Cap.ROUND);
        progressPaint.setStrokeWidth(strokeWidth);

        //初始小球画笔
        circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        circlePaint.setAntiAlias(true);
        circlePaint.setColor(circleColor);

        //竖线
        linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        linePaint.setAntiAlias(true);
        linePaint.setColor(lineColor);
        linePaint.setStrokeWidth(5);
        linePaint.setStrokeCap(Paint.Cap.ROUND);

    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        switch (configuration){
            case "horizontal":
                canvas.drawLine(WHPoint.y/2,WHPoint.y/2+space,line+WHPoint.y/2,WHPoint.y/2+space,bgPaint);
                canvas.drawLine(WHPoint.y/2,WHPoint.y/2+space,progress+WHPoint.y/2,WHPoint.y/2+space,progressPaint);
                canvas.drawCircle(progress+WHPoint.y/2,WHPoint.y/2+space,circleR,circlePaint);
                drawLine(canvas); //刻度线
                break;
        }
    }

    //刻度线
    private void drawLine(Canvas canvas){
        int k = maxProgress - minProgress;
        for (int i = 0; i <= k; i++){
            if (i != 0 && i != k){
                float x = WHPoint.y/2 + (line/(float)k *i);
                canvas.drawLine(x,2,x,10,linePaint);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (configuration){
            case "horizontal":
                horTouch(event);
                break;
        }
        return true;
    }


    private void horTouch(MotionEvent event) {
        float x = event.getX();
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                getParent().requestDisallowInterceptTouchEvent(true);
//                if (!isTure){
//                    getParent().requestDisallowInterceptTouchEvent(true);
//                    int point = ((int) x);
//                    if (point<0){
//                        point = 0;
//                    }else if (point>line){
//                        point = line;
//                    }
//                    progress = point;
//                }
                break;
            case MotionEvent.ACTION_MOVE:
                /*int pointX = ((int) x-circleR);
                if (pointX<0){
                    pointX = 0;
                }else if (pointX> line){
                    pointX = line;
                }
                progress = pointX;*/
                int pointX = ((int) x-circleR);
                if (pointX<0){
                    pointX = 0;
                }else if (pointX> line){
                    pointX = line;
                }
                Log.i("打印进度值:","pointX = "+pointX + " ,line = "+line);
                progress = pointX;

                break;
            case MotionEvent.ACTION_UP:
                getParent().requestDisallowInterceptTouchEvent(false);

                int len = maxProgress - minProgress;
                float dan = line/(float)len;

                float zuiXiao = line;
                int u = len;
                for (int i = 0; i <= len; i++){
                    //Log.i("打印i =",""+i);
                    float k = dan*i;
                    float jue = Math.abs(k- progress);//求绝对值
                    if (jue < zuiXiao){
                        zuiXiao = jue;
                        u = i;
                    }
                }
                Log.i("打印进度值zuiXiao:",""+zuiXiao);
                progress = u*dan;
                Log.i("打印进度值uu:",""+u +" ,progress = "+progress +" ,dan = "+dan +" ,line = "+line);
                if (easySeekBarLister != null){
                    value = (int)getVHValue(progress);
                    Log.i("打印进度值111:",""+value);
                    easySeekBarLister.onProgress(value);
                }
                break;
        }
        invalidate();
    }


    /**
     * @describe 绝对值
     * @param i
     * @return
     */
    private int getAbs(int i) {
        if (i<0){
            i = -i;
        }
        return i;
    }
    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        if (value < minProgress){
            this.value = minProgress;
        }else if (value > maxProgress){
            this.value = maxProgress;
        }else {
            this.value = value;
        }
        progress = ValueToProgress(this.value);
        invalidate();
    }

    private float ValueToProgress(int value) {
        switch (configuration){
            case "horizontal":
                return progress = (value-minProgress)*line/(maxProgress - minProgress);
        }
        return minProgress;
    }

    private float getVHValue(float progress) {
        return progress*(maxProgress - minProgress) / line+minProgress;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        switch (configuration){
            case "horizontal":
                setMeasuredDimension(WHPoint.x,WHPoint.y+space);
                break;
        }
    }

    public interface EasySeekBarLister{
        void onProgress(int pro);
    }

}

3、布局文件

<com.example.customseekbar.easy.StepSeekBar
        android:id="@+id/stepSeekBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="350dp"
        app:circle_color="#F6B363"
        app:circle_r="8dp"
        app:configuration="horizontal"
        app:line="300dp"
        app:max_progress="8"
        app:min_progress="0"
        app:progress_bg_color="#F7F1F7"
        app:progress_color="#FFDFB8"
        app:progress_with="15" />

    <TextView
        android:id="@+id/tv_step"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="400dp"
        android:layout_centerHorizontal="true"></TextView>

4、activity

public class HorizontalActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_horizontal);

        TextView tv_step = findViewById(R.id.tv_step);
        StepSeekBar stepSeekBar = findViewById(R.id.stepSeekBar);
        stepSeekBar.setEasySeekBarLister(new StepSeekBar.EasySeekBarLister() {
            @Override
            public void onProgress(int pro) {
                tv_step.setText(""+pro);
            }
        });

        stepSeekBar.setValue(7);
        tv_step.setText("7");
    }
}

5、color文件

   <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>

 

 

完成

posted on 2022-08-13 21:59  巫山老妖  阅读(82)  评论(0编辑  收藏  举报