自定义SeekBar,继承自view

之前项目中由于滑块功能需要的SeekBar是继承自AppCompatSeekBar,发现坑还是蛮多的,所以自己简单撸了一个。

想法很简单:判断view的touch事件,move事件时候绘制滑块按钮和进度 。然后分别在down move up事件中仿照seekBar的回调一次把onStartTouch-onProgressChange-onStopTouch回调出来。具体代码如下:

package com.example.simatu.coordinatorlayout.widget;

import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.example.simatu.coordinatorlayout.R;


public class MyCustomSeekBar extends View {
    private Context mContext;
    private Paint mProgressPaint;

    private static final String DEFAULT_TYPE = "default";
    private static final String SUCCESS_TYPE = "success";
    private static final String WRONG_TYPE = "wrong";
    private String mCurrentType = DEFAULT_TYPE;

    private float thumbCenterX;
    private int mThumbDrawable;
    private String mVerifyText;

    public void setOnProgressChangeListener(OnProgressChangeListener onProgressChangeListener) {
        this.onProgressChangeListener = onProgressChangeListener;
    }

    private OnProgressChangeListener onProgressChangeListener;

    public MyCustomSeekBar(Context context) {
        super(context);
        init(context);
    }


    public MyCustomSeekBar(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);

    }

    public MyCustomSeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        this.mContext = context;
        mVerifyText = context.getString(R.string.verifyText);
        mProgressPaint = new Paint();
        thumbCenterX = dip2px(20f);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.save();
        Rect rect = new Rect();
        Paint mTextPaint = new TextPaint();
        mTextPaint.setTextSize(50f);
        int textLength = mVerifyText == null ? 0 : mVerifyText.length();

        mTextPaint.getTextBounds(mVerifyText, 0, textLength, rect);
        int startX = getWidth() / 2;
        int startY = getHeight() / 2;
        //绘制滑块中的提示文字
        canvas.drawText(mVerifyText, startX, startY, mTextPaint);
        canvas.restore();
        mProgressPaint.setStyle(Paint.Style.FILL);//设置填充样式
        //根据滑动时的手势或者验证的结果来绘制不同的按钮和进度颜色
        switch (mCurrentType) {

            case DEFAULT_TYPE:
                mThumbDrawable = R.mipmap.slider_button_default;
                mProgressPaint.setColor(getResources().getColor(R.color.progress_default));
                break;
            case SUCCESS_TYPE:
                mThumbDrawable = R.mipmap.slider_button_success;
                mProgressPaint.setColor(getResources().getColor(R.color.progress_success));
                break;
            case WRONG_TYPE:
                mThumbDrawable = R.mipmap.slider_button_failed;
                mProgressPaint.setColor(getResources().getColor(R.color.progress_failed));
                break;

        }
        //以按钮中心为标准画进度条和按钮
        RectF rectF = new RectF(0, 0, thumbCenterX + dip2px(20f), 120); //这里top为0 bottom为控件高度
        canvas.drawRoundRect(rectF, dip2px(8f), dip2px(8f), mProgressPaint);
        //绘制按钮
        canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), mThumbDrawable), thumbCenterX - dip2px(20f), 0, null);
        canvas.restore();


    }

    @Override
    protected void onSizeChanged(int w, int h, int oldW, int oldH) {
        super.onSizeChanged(w, h, oldW, oldH);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        //根据手势滑动 改变按钮的距离并且改变进度条的进度
        // 这里的坐标只是相对于控件top 和left的距离
        float downX;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                thumbCenterX = downX;
                if (thumbCenterX < dip2px(20f)) {
                    thumbCenterX = dip2px(20f);
                    if (null != onProgressChangeListener) {
                        onProgressChangeListener.onStartTouch(this);
                    }
                }
                break;
            case MotionEvent.ACTION_MOVE:
                float moveX = event.getX();
                thumbCenterX = moveX;
                if (thumbCenterX >= dip2px(20f) || thumbCenterX <= getRight() - dip2px(20f)) {
                    if (null != onProgressChangeListener) {
                        int progress = (int) (moveX / getWidth());
                        onProgressChangeListener.onProgressChange(progress, this);
                    }
                }
                if (thumbCenterX < dip2px(20f)) {
                    thumbCenterX = dip2px(20f);
                }
                if (thumbCenterX >= getRight() - dip2px(20f)) {
                    thumbCenterX = getRight() - dip2px(20f);
                }
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                if (null != onProgressChangeListener) {
                    onProgressChangeListener.onStopTouch(this);
                }
                break;
        }

        return true;
    }

    /**
     * 禁用点击非thumb按钮区域的点击事件
     *
     * @param event
     * @return
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        //这个就是按钮的矩阵
        Rect thumbRect = new Rect(((int) (thumbCenterX - dip2px(20f))), 0, ((int) (thumbCenterX + dip2px(20f))), 120);
        int thumbLeft = thumbRect.left;
        int thumbRight = thumbRect.right;
        int thumbTop = thumbRect.top;
        int thumbBottom = thumbRect.bottom;
        int eventX = (int) event.getX();
        int eventY = (int) event.getY();
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (eventX <= thumbLeft || eventX >= thumbRight || eventY <= thumbTop || eventY >= thumbBottom) {
                return false;
            }
        }
        return super.dispatchTouchEvent(event);
    }

    /**
     * 重置进度为0
     */
    public void resetThumb() {
        thumbCenterX = dip2px(20f);
        mCurrentType = DEFAULT_TYPE;
        invalidate();
    }

    public interface OnProgressChangeListener {
        void onStartTouch(MyCustomSeekBar seekBar);

        void onProgressChange(int progress, MyCustomSeekBar seekBar);

        void onStopTouch(MyCustomSeekBar seekBar);
    }

    public int dip2px(float dipValue) {
        return (int) (dipValue * getScreenScale() + 0.5f);
    }

    /**
     * The logical density of the display.
     *
     * @return float
     */
    public float getScreenScale() {
        try {
            final float scale = mContext.getResources().getDisplayMetrics().density;
            return scale;
        } catch (Throwable e) {
            return 1;
        }
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值