管窺Android中的滑動條SeekBar的父類AbsSeekBar的源碼

來源:互聯網
上載者:User

管窺Android中的滑動條SeekBar的父類AbsSeekBar的源碼

Android中的控制項中有一類是ProgressBar,其子類中有一個是AbsSeekBar。相信有不少童鞋對這個拖動條的父類比較感興趣吧!尤其是看到網易雲音樂的進度條上面是可以處理播放與暫停事件,是不是很羨慕的哈~ 俺在這裡告訴大家,不用羨慕,看了我下面的程式碼分析,你也是可以做出那樣的效果的哦。Let's go.

下面先給大家列表一下AbsSeekBar的成員變數有哪些。

    //當前的矩形    private final Rect mTempRect = new Rect();    //可以拖動的滑塊    private Drawable mThumb;    //顏色的狀態的列表    private ColorStateList mThumbTintList = null;    //對應的連接埠的融合    private PorterDuff.Mode mThumbTintMode = null;    //是否支援的歡快的tint    private boolean mHasThumbTint = false;    //對應的是滑塊的模式    private boolean mHasThumbTintMode = false;    //滑塊的位移量    private int mThumbOffset;    //是否進行分割追蹤    private boolean mSplitTrack;
在變數中我們大致需要知道一下幾點:

1、mTempRect是與SeekBar整個軌跡繪製相關的變數

2、mThumb是SeekBar上面的滑塊的Drawable的圖片

3、mThumbOffset是滑塊是距離x左邊距的距離


對於AbsSeekBar的成員方法,下面選取一個比較重要的,在實際的開發工作中經常用到的幾個方法給大家講解一下。

1、setThumbOffset

這個方法是設定滑塊距離左邊距的位置

2、

public synchronized void setMax(int max) {        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.

關於軌跡的繪製與滑塊的繪製的更新,主要關注下面的一段代碼

if (track != null) {            track.setBounds(0, trackOffset, w - mPaddingRight - mPaddingLeft,                    h - mPaddingBottom - trackOffset - mPaddingTop);        }        if (thumb != null) {            setThumbPos(w, thumb, getScale(), thumbOffset);        }

軌跡的繪製比較重要,我們一起看看吧;

void drawTrack(Canvas canvas) {        //擷取當前滑塊的引用        final Drawable thumbDrawable = mThumb;        if (thumbDrawable != null && mSplitTrack) {            final Insets insets = thumbDrawable.getOpticalInsets();            final Rect tempRect = mTempRect;            thumbDrawable.copyBounds(tempRect);            tempRect.offset(mPaddingLeft - mThumbOffset, mPaddingTop);            tempRect.left += insets.left;            tempRect.right -= insets.right;            final int saveCount = canvas.save();            //對當前的矩形進行裁剪            canvas.clipRect(tempRect, Op.DIFFERENCE);            super.drawTrack(canvas);            canvas.restoreToCount(saveCount);        } else {            super.drawTrack(canvas);        }    }
針對上面的代碼塊,主要講下面的幾點:

1、mSlitTrack這個變數存在的原因是,我們通常遇到滑塊的左右的顏色不一樣,這個變數就是起到分割左右兩邊的目的。

滑塊的繪製也是比較重要的哦,下面也一起來看看吧:

void drawThumb(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,因此本質上是畫布在不斷的進行位移。也就是這一行代碼的含義:
canvas.translate(mPaddingLeft - mThumbOffset, mPaddingTop);
下面的內容主要是講解AbsSeekBar是如何處理touch事件,而我上面的所說的網易雲音樂如果做到點擊進度條實現播放與暫停效果也與下面的講解有關:

與上面一樣,咱們先上代碼:

public boolean onTouchEvent(MotionEvent event) {        if (!mIsUserSeekable || !isEnabled()) {            return false;        }        switch (event.getAction()) {            case MotionEvent.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;            case MotionEvent.ACTION_MOVE:                if (mIsDragging) {                    trackTouchEvent(event);                } else {                    final float 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;            case MotionEvent.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;            case MotionEvent.ACTION_CANCEL:                if (mIsDragging) {                    onStopTrackingTouch();                    setPressed(false);                }                invalidate(); // see above explanation                break;        }        return true;    }

上面的代碼,各位看官不要著急,且聽在下一一道來:

1、如果當前的SeekBar已經設定了不能夠touch操作,廢話不用多說,直接return。

2、按照源碼的解釋,噹噹前的控制項處於按下的狀態,主要進行下面的處理:

2、1 設定當前的狀態為Press的狀態

2、2 重新整理當前的視圖


如果我們需要仿造網易雲音樂,需要處理暫停音樂的邏輯,

需要注意兩點

1、判斷當前的event的x的座標是否是在滑塊的內部,如果是,不論當前的位移是多少,均不要改變當前的進度

2、修改當前的滑塊的圖片



好了,整個的源碼的講解就到這裡了,相信大家看到這裡,對Android中的SeekBar有了比以前更進一步的瞭解了吧!不用謝哦,叫我發哥就行。再見,



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.