自定义SeekBar 带文字

今天我和大家来交流一下自定义View,之前的在工作中很多控件都是找大神做好的来用,一者是没时间,项目比较着急上线,再者是自己之前一直没有研究过,前段时间所有的项目都完成的差不多了,空出来时间就久了不少自定View,那么今天就和大家一起来探讨一下SeekBar 拖动条。

       开始写之前我们先来看看android官方的SeekBar都有哪些特性

大家都知道做到音频播放和音乐播放时,我们会用SeekBar来做控制进度或者限制进度 ,看一下官方API,继承自ProgressBar,


     SeekBar是ProgressBar的扩展,在其基础上增加了一个可拖动的thumb。

今天我们要做的是把Thumb自定成可以显示文字的部分


首先我们要知道自定义View的几个步骤

1、自定义View的属性

2、获取属性值

3、重写OnMesure方法,用于测量View的宽高 (非必要)

4、重写Ondraw方法 绘制

看过以上步骤那么久开始吧 

一、自定义View属性

从效果来看,我们需要定义这些属性值

tickBarHeight 拖动条高度     tickBarColor 拖动条默认颜色     circleButtonColor 文字按钮颜色   circleButtonTextColor 文字颜色 

circleButtonTextSize 文字大小circleButtonRadius按钮半径progressHeight 进度条高度progressColor 进度条颜色 

selectProgress 进度默认值 startProgress 进度开始值 maxProgress 进度最大值 isShowButtonText显示文字标志

isShowButton 显示按钮标志 isRound 是否是圆角

在values目录下 创建attrs.xml

添加以上属性定义

<declare-styleable name="NumTipSeekBar">

   <attr name="tickBarHeight" format="dimension" />
        <attr name="tickBarColor" format="color" />
        <attr name="circleButtonColor" format="color" />
        <attr name="circleButtonTextColor" format="color" />
        <attr name="circleButtonTextSize" format="dimension" />
        <attr name="circleButtonRadius" format="dimension" />
        <attr name="progressHeight" format="dimension" />
        <attr name="progressColor" format="color" />
        <attr name="selectProgress" format="integer" />
        <attr name="startProgress" format="integer" />
        <attr name="maxProgress" format="integer" />
        <attr name="isShowButtonText" format="boolean" />
        <attr name="isShowButton" format="boolean" />
        <attr name="isRound" format="boolean" />
    </declare-styleable>

前面是属性名,后面的format是格式,数据值类型

二、接下来就是获取属性

自定义一个TipSeekBar类继承View

然后定义上述属性的对应的成员变量


 public TipSeekBar(Context context) {
        this(context, null);
    }


    public TipSeekBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }


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

三个构造方法


    private void init(Context context, AttributeSet attrs) {


        TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.NumTipSeekBar);
        mTickBarHeight = attr.getDimensionPixelOffset(R.styleable
                .NumTipSeekBar_tickBarHeight, getDpValue(8));
        mTickBarColor = attr.getColor(R.styleable.NumTipSeekBar_tickBarColor, getResources()
                .getColor(R.color.orange_f6));
        mCircleButtonColor = attr.getColor(R.styleable.NumTipSeekBar_circleButtonColor,
                getResources().getColor(R.color.white));
        mCircleButtonTextColor = attr.getColor(R.styleable.NumTipSeekBar_circleButtonTextColor,
                getResources().getColor(R.color.white));
        mCircleButtonTextSize = attr.getDimension(R.styleable
                .NumTipSeekBar_circleButtonTextSize, getDpValue(16));
        mCircleButtonRadius = attr.getDimensionPixelOffset(R.styleable
                .NumTipSeekBar_circleButtonRadius, getDpValue(16));
        mProgressHeight = attr.getDimensionPixelOffset(R.styleable
                .NumTipSeekBar_progressHeight, getDpValue(20));
        mProgressColor = attr.getColor(R.styleable.NumTipSeekBar_progressColor,
                getResources().getColor(R.color.white));
        mSelectProgress = attr.getInt(R.styleable.NumTipSeekBar_selectProgress, 0);
        mStartProgress = attr.getInt(R.styleable.NumTipSeekBar_startProgress, 0);
        mMaxProgress = attr.getInt(R.styleable.NumTipSeekBar_maxProgress, 10);
        mIsShowButtonText = attr.getBoolean(R.styleable.NumTipSeekBar_isShowButtonText, false);
        mIsShowButton = attr.getBoolean(R.styleable.NumTipSeekBar_isShowButton, true);
        mIsRound = attr.getBoolean(R.styleable.NumTipSeekBar_isRound, true);
        initView();
        attr.recycle(); //一定要记得释放,避免引起内存泄露
    }

    private void initView() {
        mProgressPaint = new Paint();
        mProgressPaint.setColor(mProgressColor);
        mProgressPaint.setStyle(Paint.Style.FILL);
        mProgressPaint.setAntiAlias(true);


        mCircleButtonPaint = new Paint();
        mCircleButtonPaint.setColor(mCircleButtonColor);
        mCircleButtonPaint.setStyle(Paint.Style.FILL);
        mCircleButtonPaint.setAntiAlias(true);


        mCircleButtonTextPaint = new Paint();
        mCircleButtonTextPaint.setTextAlign(Paint.Align.CENTER);
        mCircleButtonTextPaint.setColor(mCircleButtonTextColor);
        mCircleButtonTextPaint.setStyle(Paint.Style.FILL);
        mCircleButtonTextPaint.setTextSize(mCircleButtonTextSize);
        mCircleButtonTextPaint.setAntiAlias(true);


        mTickBarPaint = new Paint();
        mTickBarPaint.setColor(mTickBarColor);
        mTickBarPaint.setStyle(Paint.Style.FILL);
        mTickBarPaint.setAntiAlias(true);


        mTickBarRecf = new RectF();//View绘制区域的矩形,进度条区域
        mProgressRecf = new RectF();//进度条区域矩形
        mCircleRecf = new RectF();//按钮区域矩形
    }

属性以获取到

三、绘制

第三步本来是计算控件的宽高,但是由于我们这里的定义了View的宽高,所以这边就不重写onMesure方法,但是我建议大家在写自定义View的时候最好是加上这个

重写,自己计算一下View的高度

接下来就是绘制 重写onMesure

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        initValues(width, height);
        if (mIsRound) {
            canvas.drawRoundRect(mTickBarRecf, mProgressHeight / 2, mProgressHeight / 2,
                    mTickBarPaint);
            canvas.drawRoundRect(mProgressRecf, mProgressHeight / 2, mProgressHeight / 2,
                    mProgressPaint);
        } else {
            canvas.drawRect(mTickBarRecf, mTickBarPaint);
            canvas.drawRect(mProgressRecf, mProgressPaint);
        }
//        canvas.drawArc(mCircleRecf, 0, 360, true, mCircleButtonPaint);
        if (mIsShowButton) {
            canvas.drawCircle(mCirclePotionX, mViewHeight / 2, mCircleButtonRadius,
                    mCircleButtonPaint);
        }
        if (mIsShowButtonText) {
            Paint.FontMetricsInt fontMetrics = mCircleButtonTextPaint.getFontMetricsInt();
            int baseline = (int) ((mCircleRecf.bottom + mCircleRecf.top - fontMetrics.bottom -
                    fontMetrics
                            .top) / 2);
            // 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX()
            canvas.drawText(String.valueOf((mSelectProgress+progressIncrement)+progressText), mCircleRecf.centerX
                            (), baseline,
                    mCircleButtonTextPaint);
        }
    }

这里需要计算一下几个值

三个矩形的位置


这个示意图希望大家能看明白

我来说一下tickbar矩形位置计算

第一点左上角就是就是位于View的x1,y1 x1很容易 getPaddingLeft () ,没有设置paddingLeft就是0 y1的话需要计算一下 整个View的高度减去tickbar的高度,然后再除2就是距离View顶部的高度,即为tickbar的起始Y

第二点右下角x2,y2 x2 同样getPaddingLeft ()+viewWidth,y2= mTickBarHeight / 2 + mViewHeight / 2;

剩下的两个矩形就和容易了,自己分析一下,画一下图就可以得出计算公式

重要的部分来了,就是拖动按钮事件逻辑处理

onTouchEvent()重写

这里有两种情况,拖动

1、按住拖动,2点击View的某个位置改变进度条

所以需要对这个两个动作进行处理

其实这部分计算比较简单,因为进度条的高度位置是不变的,只是X在变化,那么只要获取x的位置,同时计算一下相对于整个宽度的比率就可以得出

回调一下setSelectProgress() 重新绘制一下

当然这里还要写一个回调接口,就是手触摸up时你可以做其他的逻辑处理


写到这里基本上就大功告成,代码我打包好,大家自行下载研究吧。

http://download.csdn.net/detail/luckty/9832067

希望有问题大家随时提问和交流

3QU


附上下载地址:http://download.csdn.net/detail/luckty/9832067


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值