AbsSeekBar

来源:互联网 发布:linux循环语句实例 编辑:程序博客网 时间:2024/06/05 05:18

Android中的控件中有一类是ProgressBar,其子类中有一个是AbsSeekBar。相信有不少童鞋对这个拖动条的父类比较感兴趣吧!尤其是看到网易云音乐的进度条上面是可以处理播放与暂停事件,是不是很羡慕的哈~ 俺在这里告诉大家,不用羡慕,看了我下面的代码分析,你也是可以做出那样的效果的哦。Let's go.

下面先给大家列表一下AbsSeekBar的成员变量有哪些。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//当前的矩形
privatefinal Rect mTempRect = newRect();
//可以拖动的滑块
privateDrawable mThumb;
//颜色的状态的列表
privateColorStateList mThumbTintList = null;
//对应的端口的融合
privatePorterDuff.Mode mThumbTintMode = null;
//是否支持的欢快的tint
privateboolean mHasThumbTint = false;
//对应的是滑块的模式
privateboolean mHasThumbTintMode = false;
//滑块的偏移量
privateint mThumbOffset;
//是否进行分割追踪
privateboolean mSplitTrack;
在变量中我们大致需要知道一下几点:

1、mTempRect是与SeekBar整个轨迹绘制相关的变量

2、mThumb是SeekBar上面的滑块的Drawable的图片

3、mThumbOffset是滑块是距离x左边距的距离


对于AbsSeekBar的成员方法,下面选取一个比较重要的,在实际的开发工作中经常用到的几个方法给大家讲解一下。

1、setThumbOffset

这个方法是设置滑块距离左边距的位置

2、

?
1
2
3
4
5
6
7
8
9
publicsynchronized void setMax(intmax) {
        super.setMax(max);
        if((mKeyProgressIncrement == 0) || (getMax() / mKeyProgressIncrement > 20)) {
            // It will take the user too long to change this via keys, change it
            // to something more reasonable
            //设置为比较合理的数值
            setKeyProgressIncrement(Math.max(1, Math.round((float) getMax() / 20)));
        }
    }

这个方法实际关联到两个功能。

1、设置当前的SeekBar的最大值

2、由于存在部分手机有向左的按键与向右的按键,就比如我曾经遇到过的一款三星的商务机。按照源码的逻辑,控制左按键与右按键一次位移的边距不要超过20.

关于轨迹的绘制与滑块的绘制的更新,主要关注下面的一段代码

?
1
2
3
4
5
6
7
if(track != null) {
            track.setBounds(0, trackOffset, w - mPaddingRight - mPaddingLeft,
                    h - mPaddingBottom - trackOffset - mPaddingTop);
        }
        if(thumb != null) {
            setThumbPos(w, thumb, getScale(), thumbOffset);
        }

轨迹的绘制比较重要,我们一起看看吧;

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
voiddrawTrack(Canvas canvas) {
        //获取当前滑块的引用
        finalDrawable thumbDrawable = mThumb;
        if(thumbDrawable != null&& mSplitTrack) {
            finalInsets insets = thumbDrawable.getOpticalInsets();
            finalRect tempRect = mTempRect;
            thumbDrawable.copyBounds(tempRect);
            tempRect.offset(mPaddingLeft - mThumbOffset, mPaddingTop);
            tempRect.left += insets.left;
            tempRect.right -= insets.right;
 
            finalint saveCount = canvas.save();
            //对当前的矩形进行裁剪
            canvas.clipRect(tempRect, Op.DIFFERENCE);
            super.drawTrack(canvas);
            canvas.restoreToCount(saveCount);
        }else{
            super.drawTrack(canvas);
        }
    }
针对上面的代码块,主要讲下面的几点:

1、mSlitTrack这个变量存在的原因是,我们通常遇到滑块的左右的颜色不一样,这个变量就是起到分割左右两边的目的。

滑块的绘制也是比较重要的哦,下面也一起来看看吧:

?
1
2
3
4
5
6
7
8
9
10
11
12
voiddrawThumb(Canvas canvas) {
        if(mThumb != null) {
            canvas.save();
            // Translate the padding. For the x, we need to allow the thumb to
            // draw in its extra space
            //主要是x轴上面的变化
            canvas.translate(mPaddingLeft - mThumbOffset, mPaddingTop);
            //绘制一些Canvas的对象
            mThumb.draw(canvas);
            canvas.restore();
        }
    }

我们知道,滑块的位置会随着进度而不断的位移,而绘制的本质实际上都利用了画布类Canvas,因此本质上是画布在不断的进行位移。也就是这一行代码的含义:
?
1
canvas.translate(mPaddingLeft - mThumbOffset, mPaddingTop);
下面的内容主要是讲解AbsSeekBar是如何处理touch事件,而我上面的所说的网易云音乐如果做到点击进度条实现播放与暂停的效果也与下面的讲解有关:

与上面一样,咱们先上代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
publicboolean onTouchEvent(MotionEvent event) {
        if(!mIsUserSeekable || !isEnabled()) {
            returnfalse;
        }
 
        switch(event.getAction()) {
            caseMotionEvent.ACTION_DOWN:
                if(isInScrollingContainer()) {
                    mTouchDownX = event.getX();
                }else{
                    //设置当前的状态是处于按下的状态
                    setPressed(true);
                    if(mThumb != null) {
                        invalidate(mThumb.getBounds());// This may be within the padding region
                    }
                    onStartTrackingTouch();
                    trackTouchEvent(event);
                    attemptClaimDrag();
                }
                break;
 
            caseMotionEvent.ACTION_MOVE:
                if(mIsDragging) {
                    trackTouchEvent(event);
                }else{
                    finalfloat x = event.getX();
                    //超过一定的状态
                    if(Math.abs(x - mTouchDownX) > mScaledTouchSlop) {
                        setPressed(true);
                        if(mThumb != null) {
                            invalidate(mThumb.getBounds());// This may be within the padding region
                        }
                        onStartTrackingTouch();
                        trackTouchEvent(event);
                        attemptClaimDrag();
                    }
                }
                break;
 
            caseMotionEvent.ACTION_UP:
                if(mIsDragging) {
                    trackTouchEvent(event);
                    onStopTrackingTouch();
                    setPressed(false);
                }else{
                    // Touch up when we never crossed the touch slop threshold should
                    // be interpreted as a tap-seek to that location.
                    onStartTrackingTouch();
                    trackTouchEvent(event);
                    onStopTrackingTouch();
                }
                // ProgressBar doesn't know to repaint the thumb drawable
                // in its inactive state when the touch stops (because the
                // value has not apparently changed)
                invalidate();
                break;
 
            caseMotionEvent.ACTION_CANCEL:
                if(mIsDragging) {
                    onStopTrackingTouch();
                    setPressed(false);
                }
                invalidate();// see above explanation
                break;
        }
        returntrue;
    }

上面的代码,各位看官不要着急,且听在下一一道来:

1、如果当前的SeekBar已经设置了不能够touch操作,废话不用多说,直接return。

2、按照源码的解释,当当前的控件处于按下的状态,主要进行下面的处理:

2、1 设置当前的状态为Press的状态

2、2 刷新当前的视图


如果我们需要仿造网易云音乐,需要处理暂停音乐的逻辑,

需要注意两点

1、判断当前的event的x的坐标是否是在滑块的内部,如果是,不论当前的位移是多少,均不要改变当前的进度

2、修改当前的滑块的图片



好了,整个的源码的讲解就到这里了,相信大家看到这里,对Android中的SeekBar有了比以前更进一步的了解了吧!不用谢哦,叫我发哥就行。再见,

0 0
原创粉丝点击