溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android實現垂直進度條VerticalSeekBar

發布時間:2020-10-05 23:02:28 來源:腳本之家 閱讀:223 作者:秦漢春秋 欄目:移動開發

本文實例為大家分享了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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女