Android實現(xiàn)垂直進(jìn)度條VerticalSeekBar
本文實例為大家分享了Android實現(xiàn)垂直進(jìn)度條的具體代碼,供大家參考,具體內(nèi)容如下
水平的進(jìn)度條見多了,總會想見個垂直的進(jìn)度條開開眼。今天咱就試試。
要說原理也簡單,就是把寬高倒置,其他的理論上都不需要動,發(fā)現(xiàn)問題再補(bǔ)補(bǔ)也就行了。
官方提供
官方是提供了垂直進(jìn)度條的例子源碼的,位置在android-sdk-windows\sources\android-23\com\android\example\rscamera\VerticalSeekBar.java,當(dāng)然首先你SDK中要有Android 6.0。
VerticalSeekBar.java
/** * Class to create a vertical slider */ public class VerticalSeekBar extends SeekBar { public VerticalSeekBar(Context context) { super(context); } public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public VerticalSeekBar(Context context, AttributeSet attrs) { super(context, attrs); } protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(h, w, oldh, oldw); } @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(heightMeasureSpec, widthMeasureSpec); setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); } protected void onDraw(Canvas c) { c.rotate(-90); c.translate(-getHeight(), 0); super.onDraw(c); } @Override public boolean onTouchEvent(MotionEvent event) { if (!isEnabled()) { return false; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_UP: setProgress(getMax() - (int) (getMax() * event.getY() / getHeight())); onSizeChanged(getWidth(), getHeight(), 0, 0); break; case MotionEvent.ACTION_CANCEL: break; } return true; } }
繼承SeekBar是最簡單快捷的,不用重寫太多方法,只需要把
onMeasure
onSizeChanged
onDraw
三個方法作一些改動;但也有一些問題,比如只能響應(yīng)onPregress方法,為了讓他能響應(yīng)onStartTrackingTouch和onStopTrackingTouch方法,只好再加一些代碼,于是有了改進(jìn)版。
稍作改進(jìn)
VerticalSeekBar2.java
public class VerticalSeekBar2 extends SeekBar { private Drawable mThumb; private OnSeekBarChangeListener mOnSeekBarChangeListener; public VerticalSeekBar2(Context context) { super(context); } public VerticalSeekBar2(Context context, AttributeSet attrs) { super(context, attrs); } public VerticalSeekBar2(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) { mOnSeekBarChangeListener = l; } protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(h, w, oldh, oldw); } @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(heightMeasureSpec, widthMeasureSpec); setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); } protected void onDraw(Canvas c) { c.rotate(-90); c.translate(-getHeight(), 0); super.onDraw(c); } void onProgressRefresh(float scale, boolean fromUser) { Drawable thumb = mThumb; if (thumb != null) { setThumbPos(getHeight(), thumb, scale, Integer.MIN_VALUE); invalidate(); } if (mOnSeekBarChangeListener != null) { mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), fromUser); } } private void setThumbPos(int w, Drawable thumb, float scale, int gap) { int available = w - getPaddingLeft() - getPaddingRight(); int thumbWidth = thumb.getIntrinsicWidth(); int thumbHeight = thumb.getIntrinsicHeight(); int thumbPos = (int) (scale * available + 0.5f); // int topBound = getWidth() / 2 - thumbHeight / 2 - getPaddingTop(); // int bottomBound = getWidth() / 2 + thumbHeight / 2 - getPaddingTop(); int topBound, bottomBound; if (gap == Integer.MIN_VALUE) { Rect oldBounds = thumb.getBounds(); topBound = oldBounds.top; bottomBound = oldBounds.bottom; } else { topBound = gap; bottomBound = gap + thumbHeight; } thumb.setBounds(thumbPos, topBound, thumbPos + thumbWidth, bottomBound); } public void setThumb(Drawable thumb) { mThumb = thumb; super.setThumb(thumb); } void onStartTrackingTouch() { if (mOnSeekBarChangeListener != null) { mOnSeekBarChangeListener.onStartTrackingTouch(this); } } void onStopTrackingTouch() { if (mOnSeekBarChangeListener != null) { mOnSeekBarChangeListener.onStopTrackingTouch(this); } } private void attemptClaimDrag() { if (getParent() != null) { getParent().requestDisallowInterceptTouchEvent(true); } } @Override public boolean onTouchEvent(MotionEvent event) { if (!isEnabled()) { return false; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: setPressed(true); onStartTrackingTouch(); break; case MotionEvent.ACTION_MOVE: attemptClaimDrag(); setProgress(getMax() - (int) (getMax() * event.getY() / getHeight())); break; case MotionEvent.ACTION_UP: onStopTrackingTouch(); setPressed(false); break; case MotionEvent.ACTION_CANCEL: onStopTrackingTouch(); setPressed(false); break; } return true; }
為了響應(yīng)另外兩個不知道怎么就被onPregress拋棄的方法,添了這么多代碼真是罪過,不過都是從SeekBar的父類AbsSeekBar中仿寫過來的,邏輯稍作改動就能用。
對比測試
上圖。
左邊是官方例子中的,右邊是改進(jìn)過的。
測試源碼:垂直進(jìn)度條VerticalSeekBar
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android調(diào)用系統(tǒng)自帶的分享功能實例代碼
本篇文章主要介紹了Android調(diào)用系統(tǒng)自帶的分享功能實例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-04-04Android 基于MediatorLiveData實現(xiàn)紅點(diǎn)的統(tǒng)一管理
這篇文章主要介紹了Android 基于MediatorLiveData實現(xiàn)紅點(diǎn)的統(tǒng)一管理,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下2021-04-04Android 中ActionBar+fragment實現(xiàn)頁面導(dǎo)航的實例
這篇文章主要介紹了Android 中ActionBar+fragment實現(xiàn)頁面導(dǎo)航的實例的相關(guān)資料,希望通過本文能幫助到大家實現(xiàn)這樣的功能,需要的朋友可以參考下2017-09-09Webview實現(xiàn)android簡單的瀏覽器實例代碼
這篇文章主要介紹了Webview實現(xiàn)android簡單的瀏覽器實例代碼的相關(guān)資料,需要的朋友可以參考下2016-02-02Android存儲卡讀寫文件與Application數(shù)據(jù)保存的實現(xiàn)介紹
這篇文章主要介紹了Android在存儲卡上讀寫文件、Application保存數(shù)據(jù)的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-09-09

Android編程實現(xiàn)通訊錄中聯(lián)系人的讀取,查詢,添加功能示例

Android實現(xiàn)頂部導(dǎo)航菜單左右滑動效果

Android開發(fā) -- 狀態(tài)欄通知Notification、NotificationManager詳解