完美版 竖直的SeekBar

项目中需要用到一个竖直的SeekBar


简单搜索了一下,要么不能用,要么没开源(鄙视,安卓系统都是开源的,你一个简单的demo也不开源,恶心),最好的一个是有bug的


不过没关系,bug好说,改一下就行了



废话不多说,

代码直接用就行

下面本来代码的出处已经忘记了, 


核心改动是 原来的setOnSeekBarChangeListener  =》  setOnChangedListener 用这个方法就是正常的,原始方法的开始与停止回调函数没作用



import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewParent;
import android.widget.ProgressBar;
import android.widget.SeekBar;


/**
 * 使用 setOnChangedListener 完美
 **/
public class VerticalSeekBar extends SeekBar {

	private boolean mIsDragging;
	private float mTouchDownY;
	private int mScaledTouchSlop;
	private boolean isInScrollingContainer = false;


	public boolean isInScrollingContainer() {
		return isInScrollingContainer;
	}


	public void setInScrollingContainer(boolean isInScrollingContainer) {
		this.isInScrollingContainer = isInScrollingContainer;
	}


	/**
	 * On touch, this offset plus the scaled value from the position of the
	 * touch will form the progress value. Usually 0.
	 */
	float mTouchProgressOffset;


	public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();


	}


	public VerticalSeekBar(Context context, AttributeSet attrs) {
		super(context, attrs);
	}


	public VerticalSeekBar(Context context) {
		super(context);
	}


	@Override
	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());
	}


	@Override
	protected synchronized void onDraw(Canvas canvas) {
		canvas.rotate(-90);
		canvas.translate(-getHeight(), 0);
		super.onDraw(canvas);
	}


	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (!isEnabled()) {
			return false;
		}


		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			if (isInScrollingContainer()) {


				mTouchDownY = event.getY();
			} else {
				setPressed(true);


				invalidate();
				onStartTrackingTouch();
				trackTouchEvent(event);
				attemptClaimDrag();


				onSizeChanged(getWidth(), getHeight(), 0, 0);
			}
			break;


		case MotionEvent.ACTION_MOVE:
			if (mIsDragging) {
				trackTouchEvent(event);


			} else {
				final float y = event.getY();
				if (Math.abs(y - mTouchDownY) > mScaledTouchSlop) {
					setPressed(true);


					invalidate();
					onStartTrackingTouch();
					trackTouchEvent(event);
					attemptClaimDrag();


				}
			}
			onSizeChanged(getWidth(), getHeight(), 0, 0);
			break;


		case MotionEvent.ACTION_UP:
			if (mIsDragging) {
				trackTouchEvent(event);
				onStopTrackingTouch();
				setPressed(false);


			} else {
				// Touch up when we never crossed the touch slop threshold
				// should
				// be interpreted as a tap-seek to that location.
				onStartTrackingTouch();
				trackTouchEvent(event);
				onStopTrackingTouch();


			}
			onSizeChanged(getWidth(), getHeight(), 0, 0);
			// ProgressBar doesn't know to repaint the thumb drawable
			// in its inactive state when the touch stops (because the
			// value has not apparently changed)
			invalidate();
			break;
		}
		return true;


	}


	private void trackTouchEvent(MotionEvent event) {
		final int height = getHeight();
		final int top = getPaddingTop();
		final int bottom = getPaddingBottom();
		final int available = height - top - bottom;


		int y = (int) event.getY();


		float scale;
		float progress = 0;


		// 下面是最小值
		if (y > height - bottom) {
			scale = 0.0f;
		} else if (y < top) {
			scale = 1.0f;
		} else {
			scale = (float) (available - y + top) / (float) available;
			progress = mTouchProgressOffset;
		}


		final int max = getMax();
		progress += scale * max;


		setProgress((int) progress);


	}


	/**
	 * This is called when the user has started touching this widget.
	 */
	void onStartTrackingTouch() {
		mIsDragging = true;
		listener.onStartTrackingTouch(this);
	}


	/**
	 * This is called when the user either releases his touch or the touch is
	 * canceled.
	 */
	void onStopTrackingTouch() {
		mIsDragging = false;
		listener.onStopTrackingTouch(this);
	}


	private void attemptClaimDrag() {
		ViewParent p = getParent();
		if (p != null) {
			p.requestDisallowInterceptTouchEvent(true);
		}
	}


	OnChangeListener listener;


	/**
	 * 可以监听 开始与停止函数回调
	 */
	public void setOnChangedListener(OnChangeListener Listener) {
		this.listener = Listener;
	}


	@Override
	public synchronized void setProgress(int progress) {


		super.setProgress(progress);


		onSizeChanged(getWidth(), getHeight(), 0, 0);


		if (listener != null) {
			listener.onProgressChanged(this, progress);
		}


	}


	/**
	 * A callback that notifies clients when the progress level has been
	 * changed. This includes changes that were initiated by the user through a
	 * touch gesture or arrow key/trackball as well as changes that were
	 * initiated programmatically.
	 */
	public interface OnChangeListener {


		/**
		 * Notification that the progress level has changed. Clients can use the
		 * fromUser parameter to distinguish user-initiated changes from those
		 * that occurred programmatically.
				 * @param seekBar
		 *            The SeekBar whose progress has changed
		 * @param progress
		 *            The current progress level. This will be in the range
		 *            0..max where max was set by
		 *            {@link ProgressBar#setMax(int)}. (The default value for
		 *            max is 100.)
		 * @param fromUser
		 *            True if the progress change was initiated by the user.
		 */
		void onProgressChanged(VerticalSeekBar seekBar, int progress);


		/**
		 * Notification that the user has started a touch gesture. Clients may
		 * want to use this to disable advancing the seekbar.
				 * @param seekBar
		 *            The SeekBar in which the touch gesture began
		 */
		void onStartTrackingTouch(VerticalSeekBar seekBar);


		/**
		 * Notification that the user has finished a touch gesture. Clients may
		 * want to use this to re-enable advancing the seekbar.
				 * @param seekBar
		 *            The SeekBar in which the touch gesture began
		 */
		void onStopTrackingTouch(VerticalSeekBar seekBar);
	}



}


你可能感兴趣的:(工具使用)