퍼펙트 세로로 된 SeekBar.

13722 단어 도구 사용
항목에 세로로 된 SeekBar가 필요합니다.
간단하게 검색해 봤는데 사용할 수 없거나 오픈하지 않았거나 (경멸, 안드로이드 시스템은 모두 오픈된 것이다. 너는 간단한 데모도 오픈하지 않고 구역질이 난다) 가장 좋은 것은 버그가 있는 것이다.
하지만 괜찮아요. 버그는 말하기 쉬워요. 고치면 돼요.
쓸데없는 말은 하지 말고,
코드는 그냥 쓰면 돼요.
아래 코드의 출처를 잊어버렸는데,
핵심 변동은 원래의 set On Seek Bar Change Listener = set On Changed Listener가 이 방법을 사용하는 것이 정상이며 원시적인 방법의 시작과 정지 리셋 함수는 작용하지 않는다

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);
	}



}

좋은 웹페이지 즐겨찾기