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

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

(0)

相关推荐

  • android ListView和ProgressBar(进度条控件)的使用方法

    ListView控件的使用:ListView控件里面装的是一行一行的数据,一行中可能有多列,选中一行,则该行的几列都被选中,同时可以触发一个事件,这种控件在平时还是用得很多的.使用ListView时主要是要设置一个适配器,适配器主要是用来放置一些数据.使用起来稍微有些复杂,这里用的是android自带的SimpleAdapter,形式如下:android.widget.SimpleAdapter.SimpleAdapter(Context context, List<? extends Map<

  • 实例详解Android自定义ProgressDialog进度条对话框的实现

    Android SDK已经提供有进度条组件ProgressDialog组件,但用的时候我们会发现可能风格与我们应用的整体风格不太搭配,而且ProgressDialog的可定制行也不太强,这时就需要我们自定义实现一个ProgressDialog. 通过看源码我们发现,ProgressDialog继承自Alertdialog,有一个ProgressBar和两个TextView组成的,通过对ProgressDialog的源码进行改进就可以实现一个自定义的ProgressDialog. 1.效果: 首先

  • Android三种方式实现ProgressBar自定义圆形进度条

    进度条样式在项目中经常可以见到,下面小编给大家分享Android三种方式实现ProgressBar自定义圆形进度条. Android进度条有4种风格可以使用. 默认值是progressBarStyle. 设置成progressBarStyleSmall后,图标变小. 设置成progressBarStyleLarge后,图标变大 设置成progressBarStyleHorizontal后,变成横向长方形. 自定义圆形进度条ProgressBar的一般有三种方式: 一.通过动画实现 定义res/a

  • Android 七种进度条的样式

    当一个应用在后台执行时,前台界面就不会有什么信息,这时用户根本不知道程序是否在执行.执行进度如何.应用程序是否遇到错误终止等,这时需要使用进度条来提示用户后台程序执行的进度.Android系统提供了两大类进度条样式,长形进度条(progress-BarStyleHorizontal) 和圆形进度条(progressBarStyleLarge).进度条用处很多,比如,应用程序装载资源和网络连接时,可以提示用户稍等,这一类进度条只是代表应用程序中某一部分的执行情况,而整个应用程序执行情况呢,则可以通

  • android自定义进度条渐变色View的实例代码

    最近在公司,项目不是很忙了,偶尔看见一个兄台在CSDN求助,帮忙要一个自定义的渐变色进度条,我当时看了一下进度条,感觉挺漂亮的,就尝试的去自定义view实现了一个,废话不说,先上图吧! 这个自定义的view,完全脱离了android自带的ProgressView,并且没使用一张图片,这样就能更好的降低程序代码上的耦合性! 下面我贴出代码  ,大概讲解一下实现思路吧! 复制代码 代码如下: package com.spring.progressview; import android.conten

  • Android中实现Webview顶部带进度条的方法

    写这篇文章,做份备忘,简单滴展示一个带进度条的Webview示例,进度条位于Webview上面. 示例图如下: 主Activity代码: 复制代码 代码如下: package com.droidyue.demo.webviewprogressbar; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.vi

  • Android文件下载进度条的实现代码

    main.xml: 复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_paren

  • Android ProgressBar进度条使用详解

    ProgressBar进度条,分为旋转进度条和水平进度条,进度条的样式根据需要自定义,之前一直不明白进度条如何在实际项目中使用,网上演示进度条的案例大多都是通过Button点击增加.减少进度值,使用方法incrementProgressBy(int),最简单的做法是在xml布局文件中放置ProgressBar空间,然后再MainActivity中触发事件后执行incrementProgressBy(int),代码如下: <LinearLayout xmlns:android="http:/

  • Android中自定义进度条详解

    Android原生控件只有横向进度条一种,而且没法变换样式,比如原生rom的样子 很丑是吧,当伟大的产品设计要求更换前背景,甚至纵向,甚至圆弧状的,咋办,比如: ok,我们开始吧: 一)变换前背景 先来看看progressbar的属性: 复制代码 代码如下: <ProgressBar             android:id="@+id/progressBar"             style="?android:attr/progressBarStyleHor

  • Android编程之ProgressBar圆形进度条颜色设置方法

    本文实例讲述了Android ProgressBar圆形进度条颜色设置方法.分享给大家供大家参考,具体如下: 你是不是还在为设置进度条的颜色而烦恼呢--别着急,且看如下如何解决. ProgressBar分圆形进度条和水平进度条 我这里就分享下如何设置圆形进度条的颜色吧,希望对大家会有帮助. 源码如下: 布局文件代码: <ProgressBar android:id="@+id/progressbar" android:layout_width="wrap_content

随机推荐