Android实现垂直进度条VerticalSeekBar

 更新时间:2021年01月27日 11:55:49   作者:秦汉春秋  
这篇文章主要为大家详细介绍了Android实现垂直进度条VerticalSeekBar的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了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中仿写过来的,逻辑稍作改动就能用。

对比测试

上图。

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

测试源码:垂直进度条VerticalSeekBar

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

相关文章

  • Android拍照裁剪图片

    Android拍照裁剪图片

    智能手机像素非常高,完全可以当相机使用,下面一段代码给大家分享了android拍照裁剪图片的功能,对android拍照裁剪图片相关知识感兴趣的朋友一起学习吧
    2015-12-12
  • Android 仿摩拜单车共享单车进度条实现StepView效果

    Android 仿摩拜单车共享单车进度条实现StepView效果

    这篇文章主要介绍了android 仿摩拜单车共享单车进度条实现StepView效果的实例,通过定义五个状态,分别为:为完成、正在进行、已完成、终点完成、终点未完成。具体实现代码,大家参考下
    2017-03-03
  • Android中使用ContentProvider管理系统资源的实例

    Android中使用ContentProvider管理系统资源的实例

    这篇文章主要介绍了Android中使用ContentProvider管理系统资源的实例,讲解了ContentProvider对系统中联系人及多媒体资源的管理例子,需要的朋友可以参考下
    2016-04-04
  • Android实现打开各种文件的intent方法小结

    Android实现打开各种文件的intent方法小结

    这篇文章主要介绍了Android实现打开各种文件的intent方法,结合实例形式总结分析了Android针对HTML、图片文件、pdf文件、文本文件、音频文件、视频文件等的intent打开方法,需要的朋友可以参考下
    2016-08-08
  • Android Tab 控件详解及实例

    Android Tab 控件详解及实例

    这篇文章主要介绍了Android Tab 控件详解及实例的相关资料,需要的朋友可以参考下
    2017-03-03
  • Android自定义viewgroup可滚动布局 GestureDetector手势监听(5)

    Android自定义viewgroup可滚动布局 GestureDetector手势监听(5)

    这篇文章主要为大家详细介绍了Android自定义viewgroup可滚动布局,GestureDetector手势监听,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • Android实现圆形渐变加载进度条

    Android实现圆形渐变加载进度条

    这篇文章主要为大家详细介绍了Android实现圆形渐变加载进度条,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-09-09
  • Android中判断网络连接是否可用及监控网络状态

    Android中判断网络连接是否可用及监控网络状态

    获取网络信息需要在AndroidManifest.xml文件中加入相应的权限,接下来详细介绍Android中判断网络连接是否可用及监控网络状态,感兴趣的朋友可以参考下
    2012-12-12
  • Android ListView在Fragment中的使用示例详解

    Android ListView在Fragment中的使用示例详解

    这篇文章主要介绍了Android ListView在Fragment中的使用,因为工作一直在用mvvm框架,因此这篇文章是基于mvvm框架写的,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • Android获取与设置系统环境变量的方法指南

    Android获取与设置系统环境变量的方法指南

    这篇文章主要给大家介绍了关于Android获取与设置系统环境变量的方法指南,文中通过示例代码介绍的非常详细,对各位Android开发者们具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-06-06

最新评论