首页 > 系统 > Android > 正文

Android实现垂直进度条VerticalSeekBar

2019-10-21 21:46:05
字体:
来源:转载
供稿:网友

本文实例为大家分享了Android实现垂直进度条的具体代码,供大家参考,具体内容如下

水平的进度条见多了,总会想见个垂直的进度条开开眼。今天咱就试试。 
要说原理也简单,就是把宽高倒置,其他的理论上都不需要动,发现问题再补补也就行了。

官方提供

官方是提供了垂直进度条的例子源码的,位置在android-sdk-windows/sources/android-23/com/android/example/rscamera/VerticalSeekBar.java,当然首先你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 

三个方法作一些改动;但也有一些问题,比如只能响应onPregress方法,为了让他能响应onStartTrackingTouch和onStopTrackingTouch方法,只好再加一些代码,于是有了改进版。

稍作改进

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;  }

为了响应另外两个不知道怎么就被onPregress抛弃的方法,添了这么多代码真是罪过,不过都是从SeekBar的父类AbsSeekBar中仿写过来的,逻辑稍作改动就能用。

对比测试

上图。

Android,垂直进度条,VerticalSeekBar

左边是官方例子中的,右边是改进过的。

测试源码:垂直进度条VerticalSeekBar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表