VerticalSeekBar 垂直拖动条的实现

http://blog.csdn.net/lovehong0306


继上一篇文章,SeekBar不过是在ProgressBar的基础上添加了一个控制按钮(SeekBar extends AbsSeekBar extends ProgressBar),VerticalSeekBar与VerticalProgressBar实现原理相同,都是经过旋转,宽高值互换。

这两篇文章都很简单,实在没啥可讲的,不过很实用,直接贴代码吧。

package com.custom.ui;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.AbsSeekBar;

public class VerticalSeekBar extends AbsSeekBar {

	private Drawable mThumb;

	public interface OnSeekBarChangeListener {
		void onProgressChanged(VerticalSeekBar VerticalSeekBar, int progress, boolean fromUser);

		void onStartTrackingTouch(VerticalSeekBar VerticalSeekBar);

		void onStopTrackingTouch(VerticalSeekBar VerticalSeekBar);
	}

	private OnSeekBarChangeListener mOnSeekBarChangeListener;

	public VerticalSeekBar(Context context) {
		this(context, null);
	}

	public VerticalSeekBar(Context context, AttributeSet attrs) {
		this(context, attrs, android.R.attr.seekBarStyle);
	}

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

	public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) {
		mOnSeekBarChangeListener = l;
	}

	void onStartTrackingTouch() {
		if (mOnSeekBarChangeListener != null) {
			mOnSeekBarChangeListener.onStartTrackingTouch(this);
		}
	}

	void onStopTrackingTouch() {
		if (mOnSeekBarChangeListener != null) {
			mOnSeekBarChangeListener.onStopTrackingTouch(this);
		}
	}

	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();
		available -= thumbWidth;
		
		// The extra space for the thumb to move on the track
		available += getThumbOffset() * 2;
		
		int thumbPos = (int) (scale * available);
		
		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);
	}

	@Override
	protected void onDraw(Canvas c) {
		c.rotate(-90);//反转90度,将水平SeekBar竖起来  
		c.translate(-getHeight(), 0);//将经过旋转后得到的VerticalSeekBar移到正确的位置,注意经旋转后宽高值互换 
		super.onDraw(c);
	}

	@Override
	protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(heightMeasureSpec, widthMeasureSpec);
		setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());//宽高值互换
	}

	@Override
	public void setThumb(Drawable thumb) {
		mThumb = thumb;
		super.setThumb(thumb);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(h, w, oldw, oldh);//宽高值互换
	}

	//与源码完全相同,仅为调用宽高值互换处理的onStartTrackingTouch()方法
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (!isEnabled()) {
			return false;
		}
		switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN:
				setPressed(true);
				onStartTrackingTouch();
				trackTouchEvent(event);
				break;

			case MotionEvent.ACTION_MOVE:
				trackTouchEvent(event);
				attemptClaimDrag();
				break;

			case MotionEvent.ACTION_UP:
				trackTouchEvent(event);
				onStopTrackingTouch();
				setPressed(false);
				// 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;

			case MotionEvent.ACTION_CANCEL:
				onStopTrackingTouch();
				setPressed(false);
				invalidate(); // see above explanation
				break;
		}
		return true;
	}

	//宽高值互换处理
	private void trackTouchEvent(MotionEvent event) {
		final int height = getHeight();
		final int available = height - getPaddingBottom() - getPaddingTop();
		int Y = (int) event.getY();
		float scale;
		float progress = 0;
		if (Y > height - getPaddingBottom()) {
			scale = 0.0f;
		} else if (Y < getPaddingTop()) {
			scale = 1.0f;
		} else {
			scale = (float) (height - getPaddingBottom() - Y) / (float) available;
		}
		final int max = getMax();
		progress = scale * max;
		setProgress((int) progress);
	}

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

http://blog.csdn.net/lovehong0306

你可能感兴趣的:(Android)