自定义的seekBar(二)

因为很多时候seekbar并不能满足我们开发的需求,这里我们需要自定义的seekbar

上效果图,图片如下,很多人有疑问,为什么这个自定义的看起来比系统自带的效果也好不类多少,为什么还需要自定义呢,很简单,自定义可以控制很多属性,实现一些系统控件无法实现的效果,更关键的时帮助你理解源码,自定义写多了自然就会写了,这是一个长期积累的过程,大家坚持住,自定义控件不是一朝一夕能学会的,注意积累

(1)首先我们在text.xml中来定义控件,注意控件的包名

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:mhsb_seekbar="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="50dp">

    <TextView
        android:id="@+id/tv_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/app_name"
        android:gravity="center"
        />

    <com.example.administrator.testz.MHS_SeekBar
        android:id="@+id/id_sbi_0"
        android:layout_width="220dp"
        android:layout_height="30dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_gravity="center_vertical"
        android:layout_weight="1"
        android:thumb="@drawable/chs_mhs_seekbar_thumb"
        mhsb_seekbar:mhs_progress_background_color="@color/mcl_seekbar_pbg_color"
        mhsb_seekbar:mhs_progress_color="@color/mcl_seekbar_progress_color"
        mhsb_seekbar:mhs_progress_max="66"
        mhsb_seekbar:mhs_progress_width="3dp" />


</LinearLayout>

(2)在drawable里面新建一个chs_mhs_seekbar_thumb.xml,这个用于设置进度条上面拖动条的图片

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:state_activated="false"
        android:state_pressed="false"
        android:drawable="@mipmap/chs_mhs_thumb_normal"/>
    <item
        android:state_activated="true"
        android:state_pressed="false"
        android:drawable="@mipmap/chs_mhs_thumb_normal" />
    <item
        android:state_activated="false"
        android:state_pressed="true"
        android:drawable="@mipmap/chs_mhs_thumb_normal"/>
    <item
        android:state_activated="true"
        android:state_pressed="true"
        android:drawable="@mipmap/chs_mhs_thumb_normal" />
</selector>

(3)在values文件夹里面新建attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="mhsb_seekbar">
        <attr name="android:thumb" />
        <attr name="mhs_numtext_size" format="dimension" />
        <attr name="mhs_numtext_color" format="color" />
        <attr name="mhs_progress_width" format="dimension" />
        <attr name="mhs_progress_bar_round" format="dimension" />
        <attr name="mhs_progress_background_color" format="color" />
        <attr name="mhs_progress_color" format="color" />
        <attr name="mhs_progress_max" format="integer" />
    </declare-styleable>

</resources>

(4)color资源,应该都知道放哪里吧

    <color name="text_color_xoverset">#FFffffff</color>

    <!-- 输出音量调节的seekbar -->
    <color name="mcl_seekbar_progress_color">#FF9B3A</color>
    <color name="mcl_seekbar_pbg_color">#FF262c37</color>

(5)自定义的seekbar    新建MHS_SeekBar

package com.example.administrator.testz;

/**
 * Created by Administrator on 2018\7\30 0030.
 */



        import android.R.color;
        import android.content.Context;
        import android.content.res.TypedArray;
        import android.graphics.Canvas;
        import android.graphics.Paint;
        import android.graphics.RectF;
        import android.graphics.drawable.Drawable;
        import android.util.AttributeSet;
        import android.util.Log;
        import android.view.MotionEvent;
        import android.view.View;

public class MHS_SeekBar extends View {

    private final boolean DEBUG = false;
    private final String TAG = "MHS_SeekBar";

    private Context mContext = null;
    private AttributeSet mAttrs = null;

    private Drawable mThumbDrawable = null;
    private int mThumbHeight = 0;
    private int mThumbWidth = 0;
    private int[] mThumbNormal = null;
    private int[] mThumbPressed = null;
    private boolean CanTouch=true;
    private boolean ThumbTouch=false;
    private float mSeekBarMax = 0;
    private float mThumbX = 0;
    private float mThumbY = 0;
    private Paint mhsSeekBarBackgroundPaint = null;
    private Paint mhsSeekbarProgressPaint = null;
    private RectF RectF_mhsbg = null;
    private RectF RectF_mhsprogress = null;
    private float mhsSeekbarLong=0;
    private int mhsSeekbarWidth=0;
    private int mhsSeekbarRound=0;
    private float mhsprogress_set = 0;
    private int sb_left=0;
    private int sb_top=0;
    private int sb_right=0;
    private int sb_bottom=0;

    private int mViewHeight = 0;
    private int mViewWidth = 0;
    //private int mSeekBarCenterX = 0;
    private int mSeekBarCenterY = 0;
    private int mCurrentProgress = 0;
    private int old_mCurrentProgress = 0;
    /*�¼����� */
    private OnMSBSeekBarChangeListener mOnMSBSeekBarChangeListener=null;

    public MHS_SeekBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;
        mAttrs = attrs;
        initView();
    }

    public MHS_SeekBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        mAttrs = attrs;
        initView();
    }

    public MHS_SeekBar(Context context) {
        super(context);
        mContext = context;
        initView();
    }

    private void initView(){
        if(DEBUG) Log.d(TAG, "initView");
        TypedArray localTypedArray = mContext.obtainStyledAttributes(mAttrs, R.styleable.mhsb_seekbar);

        //thumb��������ʹ��android:thumb���Խ������õ�
        //���ص�DrawableΪһ��StateListDrawable���ͣ�������ʵ��ѡ��Ч����drawable list
        //mThumbNormal��mThumbPressed�����������ò�ͬ״̬��Ч���������thumbʱ����mThumbPressed����������mThumbNormal
        mThumbDrawable = localTypedArray.getDrawable(R.styleable.mhsb_seekbar_android_thumb);
        mThumbWidth = this.mThumbDrawable.getIntrinsicWidth();
        mThumbHeight = this.mThumbDrawable.getIntrinsicHeight();

        mThumbNormal = new int[]{-android.R.attr.state_focused, -android.R.attr.state_pressed,
                -android.R.attr.state_selected, -android.R.attr.state_checked};
        mThumbPressed = new int[]{android.R.attr.state_focused, android.R.attr.state_pressed,
                android.R.attr.state_selected, android.R.attr.state_checked};
        localTypedArray.getDimension(R.styleable.mhsb_seekbar_mhs_progress_width, 5);
        mhsSeekbarWidth = (int) localTypedArray.getDimension(R.styleable.mhsb_seekbar_mhs_progress_width, 5);
        mhsSeekbarRound = (int) localTypedArray.getDimension(R.styleable.mhsb_seekbar_mhs_progress_bar_round, 4);

        int progressBackgroundColor = localTypedArray.getColor(R.styleable.mhsb_seekbar_mhs_progress_background_color, color.darker_gray);
        int progressFrontColor = localTypedArray.getColor(R.styleable.mhsb_seekbar_mhs_progress_color, getResources().getColor(R.color.text_color_xoverset));
        mSeekBarMax = localTypedArray.getInteger(R.styleable.mhsb_seekbar_mhs_progress_max, 60);
        //----
        mhsSeekBarBackgroundPaint = new Paint();
        mhsSeekbarProgressPaint = new Paint();

        mhsSeekBarBackgroundPaint.setColor(progressBackgroundColor);
        mhsSeekbarProgressPaint.setColor(progressFrontColor);

        mhsSeekBarBackgroundPaint.setAntiAlias(true);
        mhsSeekbarProgressPaint.setAntiAlias(true);

        localTypedArray.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        setMeasuredDimension(width, height);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(DEBUG) Log.d(TAG, "onMeasure");
        mViewWidth = width;//getWidth();
        mViewHeight = height;//getHeight();

        //mSeekBarCenterX = mViewWidth / 2;
        mSeekBarCenterY = mViewHeight / 2;
        //mhsSeekbarLong = mViewWidth-mThumbWidth;
        mhsSeekbarLong = mViewWidth-mThumbWidth*2;
        //seekbar chs_progress and bar start point and stop point
        //sb_left=mThumbWidth/2;
        sb_left=mThumbWidth;

        sb_top=mSeekBarCenterY-mhsSeekbarWidth/2;
        sb_right=(int) (sb_left+mhsSeekbarLong);
        sb_bottom=mSeekBarCenterY+mhsSeekbarWidth/2;

        //seekbar chs_progress
        mhsprogress_set= mhsSeekbarLong/mSeekBarMax*mCurrentProgress;
        //draw Rect seekbar bg
        RectF_mhsbg = new RectF(sb_left,sb_top,sb_right,sb_bottom);
        //draw Rect seekbar chs_progress
        RectF_mhsprogress = new RectF(sb_left,sb_top,mhsprogress_set,sb_bottom);
        //seekbar Thumb
        mThumbX=mhsprogress_set + mThumbWidth/2;
        mThumbY=mSeekBarCenterY-mThumbHeight/2;
        if(DEBUG) System.out.println("MHS mViewWidth:"+mViewWidth);
        if(DEBUG) System.out.println("MHS mViewHeight:"+mViewHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int p_top=(int) (mhsprogress_set+mThumbWidth);

//    	int top=sb_top-mhsSeekbarWidth/2;
//    	int bottom=sb_bottom+mhsSeekbarWidth/2;
//    	RectF_mhsprogress = new RectF(sb_left,top,p_top,bottom);

        RectF_mhsprogress = new RectF(sb_left,sb_top,p_top,sb_bottom);
        //±³¾°£¬½ø¶È£¬½¹µã
        canvas.drawRoundRect(RectF_mhsbg, mhsSeekbarRound, mhsSeekbarRound, mhsSeekBarBackgroundPaint);
        canvas.drawRoundRect(RectF_mhsprogress, mhsSeekbarRound, mhsSeekbarRound, mhsSeekbarProgressPaint);
        drawThumbBitmap(canvas);
        //drawProgressText(canvas);

        super.onDraw(canvas);
    }

    private void drawThumbBitmap(Canvas canvas) {
        this.mThumbDrawable.setBounds((int) mThumbX, (int) mThumbY,
                (int) (mThumbX + mThumbWidth), (int) (mThumbY + mThumbHeight));
        this.mThumbDrawable.draw(canvas);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(!CanTouch){
            return true;
        }
        float eventX = event.getX();
        float eventY = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //Log.v(TAG, "MHS ACTION_DOWN eventX = " + eventX);
                if(((eventX+mThumbWidth/4)>mThumbX)&&((eventX-mThumbWidth)<mThumbX)){
                    ThumbTouch=true;
                }else{
                    ThumbTouch=false;
                }
                break ;

            case MotionEvent.ACTION_MOVE:
                //Log.v(TAG, "MHS ACTION_MOVE eventX = " + eventX);
                seekTo(eventX, eventY, ThumbTouch, true);
                break ;

            case MotionEvent.ACTION_UP:
                seekTo(eventX, eventY, false, false);
                //ThumbTouch=true;
                mThumbDrawable.setState(mThumbNormal);
                invalidate();
                break ;
            default:
                seekTo(eventX, eventY, false, false);
                //ThumbTouch=false;
                mThumbDrawable.setState(mThumbNormal);
                invalidate();
                break;
        }
        return ThumbTouch;
    }

    private void seekTo(float eventX, float eventY, boolean isUp, boolean boolean_MotionEvent) {
        eventX -= mThumbWidth/4;
        if(CanTouch==true){
            if (true == isUp) {
                mThumbDrawable.setState(mThumbPressed);
                if((eventX>mhsSeekbarWidth/4)&&(eventX < (mhsSeekbarLong))){
                    mCurrentProgress =(int) (mSeekBarMax * eventX / mhsSeekbarLong);
                }else if(eventX>mhsSeekbarLong){
                    mCurrentProgress = (int) mSeekBarMax;
                }else if(eventX<mhsSeekbarWidth/4){
                    mCurrentProgress = 0;
                }

                if ((mOnMSBSeekBarChangeListener != null)&&(mCurrentProgress!=old_mCurrentProgress)){
                    old_mCurrentProgress=mCurrentProgress;
                    mOnMSBSeekBarChangeListener.onProgressChanged(this, mCurrentProgress, boolean_MotionEvent);
                }

                mhsprogress_set= mhsSeekbarLong/mSeekBarMax*mCurrentProgress;
                //mThumbY=mhsprogress_set+mThumbHeight/2;
                mThumbX=mhsprogress_set + mThumbWidth/2;

                //Log.v(TAG, "MHS mCurrentProgress = " + mCurrentProgress);

                invalidate();
            }else{
                if ((mOnMSBSeekBarChangeListener != null)&&(mCurrentProgress!=old_mCurrentProgress)){
                    old_mCurrentProgress=mCurrentProgress;
                    mOnMSBSeekBarChangeListener.onProgressChanged(this, mCurrentProgress, false);
                }
                mThumbDrawable.setState(mThumbNormal);
                invalidate();
            }
        }else if(CanTouch==false){
            if ((mOnMSBSeekBarChangeListener != null)&&(mCurrentProgress!=old_mCurrentProgress)){
                old_mCurrentProgress=mCurrentProgress;
                mOnMSBSeekBarChangeListener.onProgressChanged(this, mCurrentProgress, boolean_MotionEvent);
            }
        }
    }
    /*
     * ����setCanTouch������������java�������
     */
    public void setTouch(boolean touch){
        CanTouch=touch;
    }

    /*
     * ����set������������java�������
     */
    public void setProgress(int progress) {
        CanTouch=true;//�ڸ������ʱ�����setProgress(),��ʱ�ɻ���
        if(DEBUG) Log.v(TAG, "setProgress chs_progress = " + progress);
        if (progress > mSeekBarMax){
            progress = (int) mSeekBarMax;
        }
        if (progress < 0){
            progress = 0;
        }
        mCurrentProgress = progress;

        mhsprogress_set= mhsSeekbarLong/mSeekBarMax*mCurrentProgress;
        //mThumbY=mhsprogress_set+mThumbHeight/2;
        mThumbX=mhsprogress_set + mThumbWidth/2;
        //if (mOnMSBSeekBarChangeListener != null){
        //	mOnMSBSeekBarChangeListener.onProgressChanged(this, mCurrentProgress, false);
        //}�����ã�
        invalidate();
    }

    public int getProgress(){
        return mCurrentProgress;
    }

    public void setProgressMax(int max){
        if(DEBUG) Log.v(TAG, "setProgressMax max = " + max);
        mSeekBarMax = max;
    }

    public int getProgressMax(){
        return (int) mSeekBarMax;
    }

    public void setProgressThumb(int thumbId){
        mThumbDrawable = mContext.getResources().getDrawable(thumbId);
    }

    public void setProgressBackgroundColor(int color){
        mhsSeekBarBackgroundPaint.setColor(color);
    }

    public void setProgressFrontColor(int color){
        mhsSeekbarProgressPaint.setColor(color);
    }

    public void setIsShowProgressText(boolean isShow){
    }

    public void setOnSeekBarChangeListener(OnMSBSeekBarChangeListener l) {
        mOnMSBSeekBarChangeListener = l;
    }

    public interface OnMSBSeekBarChangeListener {

        public abstract void onProgressChanged(MHS_SeekBar mhs_SeekBar,
                                               int progress, boolean fromUser);

    }
}

(6)只剩下监听事件了

public class MainActivity extends AppCompatActivity {

    private MHS_SeekBar VSB_Master;
    private TextView tv_main;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test);
        VSB_Master = (MHS_SeekBar) findViewById(R.id.id_sbi_0);
        tv_main = (TextView)findViewById(R.id.tv_main);

        VSB_Master.setOnSeekBarChangeListener(new MHS_SeekBar.OnMSBSeekBarChangeListener() {
            @Override
            public void onProgressChanged(MHS_SeekBar mcSeekBar, int progress, boolean fromUser) {
                tv_main.setText(String.valueOf(progress));
            }
        });

    }
}

猜你喜欢

转载自blog.csdn.net/cf8833/article/details/81291150