自定义View之组合控件

组合控件

开发自定义View对于初中级开发者都是一个比较头痛的问题,工作中遇到一个需求,需要做一个自定义的SeekBar,效果图如下所示,看到这个需求的时候,我觉得可以使用组合控件的方式来封装一个自定义的SeekBar,那么让我们开始吧!
自定义View之组合控件_第1张图片

组件介绍

  1. 首先组合控件需要继承我们android中的几大布局,这里我继承的是RelativeLayout
  2. seekBar功能介绍
    上述图片中的seekBar大致可分为4种,他们都可设置seekBar的激活状态和禁止使用状态,分别对应上面的黄色进度条和灰色进度条。
    (1)左右两张图片的seekBar。
    (2)左边图片右边文字的seekBar:右边的文字部分可随着滑动滑块显示不同的数值。
    (3)两边都是文字的seekBar:左边文字通常为设置的固定文字,右边随着seekBar滑动显示不同的数值。
    (4)两端都有滑块的seekBar:此seekBar适用于范围筛选,已提供方法获取左右两边的数值。
    (5)还有一个图片上没有体现,左右是加减符号的seekBar:此seekBar可点击加减符号来进行数值的加减,并在seekBar上体现,也可滑动滑块来设置数值。

主体代码

public class SeekBarView extends RelativeLayout {

    /**
     * 左边图片
     */
    private ImageView mIvLeft;

    /**
     * 右边图片
     */
    private ImageView mIvRight;

    /**
     * 原生的seekBar对象
     */
    private SeekBar mSeekBar;

    /**
     * 滑块
     */
    private Drawable mThumbDrawable;

    /**
     * 当前进度
     */
    private int mProgress;

    /**
     * 左边text
     */
    private TextView mTvLeft;

    /**
     * 右边text
     */
    private TextView mTvRight;

    /**
     * 左右都是image
     */
    public static final int IMAGE_IMAGE = 1;

    /**
     * 左边image,右边text
     */
    public static final int IMAGE_TEXT = 2;

    /**
     * 左右两边都是text
     */
    public static final int TEXT_TEXT = 3;

    /**
     * 加减操作模式
     */
    public static final int OPERATE_IMAGE = 4;

    /**
     * 首尾皆可滑动
     */
    public static final int RANGE_SEEKBAR = 5;
    /**
     * 当前设置的seekBar模式
     */
    private int mCurrentMode;

    /**
     * 设置的seekBar最大值
     */
    private int mMaxValue = -1;

    /**
     * 加减点击的监听
     */
    private onAddRemoveProgressListener mListener;
    /**
     * seekBar滑动监听
     */
    private onSeekBarChangeListener mOnSeekBarChangeListener;
    private RangeSeekBar mRangeSeekBar;

    private Context mContext;

    public SeekBarView(Context context) {
        super(context);
    }

    public SeekBarView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        init();

    }

    public SeekBarView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init() {

        LayoutInflater.from(mContext).inflate(R.layout.seek_bar_view, this);
        mIvLeft = findViewById(R.id.iv_left);
        mIvRight = findViewById(R.id.iv_right);
        mTvLeft = findViewById(R.id.tv_left);
        mTvRight = findViewById(R.id.tv_right);
        mSeekBar = findViewById(R.id.seek_bar);
        mThumbDrawable = getResources().getDrawable(R.drawable.thumb_click);
        //设置滑块
        mSeekBar.setThumb(mThumbDrawable);
        mRangeSeekBar = findViewById(R.id.range_seek_bar);
        //给原生的seekBar设置滑动监听
        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if(mOnSeekBarChangeListener!=null){
                    mOnSeekBarChangeListener.onProgress(progress);
                }
                mProgress = progress;
                mTvRight.setText(String.valueOf(progress));

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }

    /**
     * 设置seekBar的模式
     *
     * @param mode
     */
    public void setMode(int mode) {

        mCurrentMode = mode;
        if (mode == IMAGE_IMAGE) {
            mIvLeft.setVisibility(VISIBLE);
            mIvRight.setVisibility(VISIBLE);
        }

        if (mode == IMAGE_TEXT) {
            mIvLeft.setVisibility(VISIBLE);
            mTvRight.setVisibility(VISIBLE);
            mTvRight.setText(String.valueOf(mProgress));
        }

        if (mode == TEXT_TEXT) {
            mTvLeft.setVisibility(VISIBLE);
            mTvRight.setVisibility(VISIBLE);
        }

        if (mode == OPERATE_IMAGE) {
            mIvLeft.setImageResource(R.drawable.ic_remove_48px);
            mIvRight.setImageResource(R.drawable.ic_add_48px);
            mIvLeft.setVisibility(VISIBLE);
            mIvRight.setVisibility(VISIBLE);
            initListener();
        }

        if (mode == RANGE_SEEKBAR) {

            mSeekBar.setVisibility(GONE);
            mRangeSeekBar.setVisibility(VISIBLE);
            mTvLeft.setVisibility(VISIBLE);
            mTvRight.setVisibility(VISIBLE);
            /**
             * 双向滑动seekBar设置监听
             */
            mRangeSeekBar.setOnRangeChangedListener(new OnRangeChangedListener() {
                @Override
                public void onRangeChanged(RangeSeekBar view, float min, float max, boolean isFromUser) {

                    int mi = (int) min;
                    int mx = (int) max;
                    mTvLeft.setText(String.valueOf(mi));
                    mTvRight.setText(String.valueOf(mx));

                }

                @Override
                public void onStartTrackingTouch(RangeSeekBar view, boolean isLeft) {

                }

                @Override
                public void onStopTrackingTouch(RangeSeekBar view, boolean isLeft) {

                }
            });

        }
    }

    /**
     * 初始化加减按钮监听
     */
    private void initListener() {

        mIvLeft.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mProgress > 0) {
                    mProgress--;
                }
                mSeekBar.setProgress(mProgress);
                mListener.onProgressBack(mProgress);
            }
        });

        mIvRight.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {

                if (mMaxValue != -1) {
                    if (mProgress < mMaxValue) {
                        mProgress++;
                    }
                }
                mSeekBar.setProgress(mProgress);
                mListener.onProgressBack(mProgress);
            }
        });

    }

    /**
     * 设置seekBar是否可滑动和加减操作是否有效
     *
     * @param b 是否禁用  false:禁用 true:开启
     */
    public void setSeekBarStatus(int mode, boolean b) {

        if (mode == RANGE_SEEKBAR) {
            if (b) {
                mRangeSeekBar.setEnabled(true);
                mRangeSeekBar.getLeftSeekBar().setThumbDrawableId(R.drawable.thumb_click);
                mRangeSeekBar.getRightSeekBar().setThumbDrawableId(R.drawable.thumb_click);
                mRangeSeekBar.setProgressColor(ContextCompat.getColor(mContext, R.color.c201));
            } else {
                mRangeSeekBar.setEnabled(false);
                mRangeSeekBar.getLeftSeekBar().setThumbDrawableId(R.drawable.thumb_unclick);
                mRangeSeekBar.getRightSeekBar().setThumbDrawableId(R.drawable.thumb_unclick);
                mRangeSeekBar.setProgressColor(ContextCompat.getColor(mContext, R.color.c125));
            }
        } else {
            if (b) {
                mSeekBar.setEnabled(true);
                /**
                 * 设置滑动块
                 */
                mThumbDrawable = getResources().getDrawable(R.drawable.thumb_click);
                mSeekBar.setThumb(mThumbDrawable);
                /**
                 * 设置seekBar背景和滑过部分的颜色
                 */
                Drawable drawable = getResources().getDrawable(R.drawable.seekbar_clickable_colors);
                /**
                 * 为了解决设置背景时,seekBar宽度变化的问题
                 */
                Rect bounds = mSeekBar.getProgressDrawable().getBounds();
                mSeekBar.setProgressDrawable(drawable);
                mSeekBar.getProgressDrawable().setBounds(bounds);
                /**
                 * seekBar设置背景颜色及滑过部分颜色
                 */
                mSeekBar.setProgressDrawable(drawable);
                mIvLeft.setClickable(true);
                mIvRight.setClickable(true);
            } else {
                mSeekBar.setEnabled(false);
                mThumbDrawable = getResources().getDrawable(R.drawable.thumb_unclick);
                mSeekBar.setThumb(mThumbDrawable);
                Drawable drawable = getResources().getDrawable(R.drawable.seekbar_unclickable_colors);
                Rect bounds = mSeekBar.getProgressDrawable().getBounds();
                mSeekBar.setProgressDrawable(drawable);
                mSeekBar.getProgressDrawable().setBounds(bounds);
                mIvLeft.setClickable(false);
                mIvRight.setClickable(false);
            }
        }
    }

    /**
     * 除RANGE_SEEKBAR模式下,用于设置seekBar的最大值
     *
     * @param value
     */
    public void setMax(int value) {

        if(mCurrentMode != RANGE_SEEKBAR){
            mMaxValue = value;
            mSeekBar.setMax(value);
        }
    }

    /**
     * 除RANGE_SEEKBAR、IMAGE_IMAGE、OPERATE_IMAGE模式下,用于设置seekBar当前值
     *
     * @param value
     */
    public void setCurrentProgress(int value) {

        mSeekBar.setProgress(value);
        if (mCurrentMode != RANGE_SEEKBAR&&mCurrentMode!=IMAGE_IMAGE&&mCurrentMode!=OPERATE_IMAGE) {
            mTvRight.setText(String.valueOf(value));
            mSeekBar.setProgress(value);
        }
    }

    /**
     * 除RANGE_SEEKBAR模式,用于获取当前进度
     * @return
     */
    public int getCurrentProgress(){

        return mProgress;

    }

    /**
     * 设置左边图片资源
     *
     * @param r
     */
    public void setLeftImage(int r) {

        if (mCurrentMode != RANGE_SEEKBAR&&mCurrentMode!=TEXT_TEXT) {
            mIvLeft.setVisibility(VISIBLE);
            mIvLeft.setImageResource(r);
        }

    }

    /**
     * 设置右边图片资源
     *
     * @param r
     */
    public void setRightImage(int r) {

        if (mCurrentMode != RANGE_SEEKBAR&&mCurrentMode!=TEXT_TEXT) {
            mIvRight.setVisibility(VISIBLE);
            mIvRight.setImageResource(r);
        }

    }

    /**
     * 设置左边文字
     *
     * @param t
     */
    public void setLeftText(String t) {

        if(mCurrentMode==TEXT_TEXT) {
            mTvLeft.setText(t);
        }
    }

    /**
     * 加减模式下使用,初始化加减点击监听
     *
     * @param listener
     */
    public void setOnAddRemoveProgressListener(onAddRemoveProgressListener listener) {

        mListener = listener;

    }

    /**
     * 加减模式下使用,加减点击监听
     */
    public interface onAddRemoveProgressListener {

        void onProgressBack(int progress);

    }
    public interface onSeekBarChangeListener{

        void onProgress(int progress);

    }

    /**
     * seekBar滑动监听
     * @param listener
     */

    public void setOnSeekBarChangeListener(onSeekBarChangeListener listener){
        mOnSeekBarChangeListener = listener;
    }

    /**
     * 仅限RANGE_SEEKBAR模式下使用,用于设置seekbar的最小最大范围
     *
     * @param min
     * @param max
     */
    public void setRangeValue(int min, int max) {

        mRangeSeekBar.setRangeRules(min, max, 5, 1);
        mTvLeft.setText(String.valueOf(min));
        mTvRight.setText(String.valueOf(max));

    }

    /**
     * 获取左边text的值
     *
     * @return
     */
    public String getLeftTextValue() {
        return mTvLeft.getText().toString();
    }

    /**
     * 获取右边text的值
     *
     * @return
     */
    public String getRightTextValue() {
        return mTvRight.getText().toString();
    }

    /**
     * 当RANGE_SEEKBAR模式下需要设置背景时,调用此方法,seekbar整个的背景颜色需要在Activity中设置,在配合此方法方可达到效果
     */
    public void setRangeModelBackgroundSettings(){

        mTvLeft.setTextColor(ContextCompat.getColor(mContext,R.color.c126));
        mTvRight.setTextColor(ContextCompat.getColor(mContext,R.color.c126));
        mRangeSeekBar.setProgressDefaultColor(ContextCompat.getColor(getContext(), R.color.c125));

    }
}

SeekBar的背景的颜色资源文件代码


<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <shape>
            <solid android:color="#e0e0e0"/>
        shape>
    item>

    <item android:id="@android:id/secondaryProgress">
        <clip>
            <shape>
                <solid android:color="#11ce33"/>
            shape>
        clip>
    item>

    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <solid android:color="#ffa516" />
            shape>
        clip>
    item>
layer-list>

你可能感兴趣的:(自定义View之组合控件)