android竖直seekbar

本文详细介绍了如何自定义实现一个可调节宽度的垂直滚动条,并对其按键事件进行了响应,使得滚动条能够与遥控器上下键联动。通过XML文件在布局中引入该滚动条,展示了其在实际应用中的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考了:http://blog.youkuaiyun.com/failure01/article/details/8577675

做了如下修改:

1,修改宽度使宽度可以调节;

2,修改了按键事件,使之响应遥控器的上下按键,并且释放了左右按键;

public class VerticalSeekBar extends AbsSeekBar {

	private String TAG = "VerticalSeekBar";
	private int height = -1;
	private int width = -1;

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

		public void onStartTrackingTouch(VerticalSeekBar vBar);

		public void onStopTrackingTouch(VerticalSeekBar vBar);
	}

	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 = null;
		try {
			Field mThumb_f = this.getClass().getSuperclass()
					.getDeclaredField("mThumb");
			mThumb_f.setAccessible(true);
			thumb = (Drawable) mThumb_f.get(this);
		} catch (Exception e) {
			e.printStackTrace();
		}

		setThumbPos(getWidth(), 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 = 0;
		try {

			int up = getPaddingTop();
			int bottom = getPaddingBottom();

			available = getHeight() - up - bottom;
			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;
			}
			// Canvas will be translated, so 0,0 is where we start drawing
			thumb.setBounds(thumbPos, topBound, thumbPos + thumbWidth,
					bottomBound);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	protected synchronized void onMeasure(int widthMeasureSpec,
			int heightMeasureSpec) {
		width = View.MeasureSpec.getSize(widthMeasureSpec);
		height = View.MeasureSpec.getSize(heightMeasureSpec);

		this.setMeasuredDimension(width, height);
	}

	protected void onDraw(Canvas c) {
		c.rotate(-90);
		c.translate(-height, 0);
		super.onDraw(c);
	}

	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(h, w, oldw, oldh);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {

		boolean mIsUserSeekable = true;
		try {
			Field mIsUserSeekable_f = this.getClass().getSuperclass()
					.getDeclaredField("mIsUserSeekable");
			mIsUserSeekable_f.setAccessible(true);

			mIsUserSeekable = mIsUserSeekable_f.getBoolean(this);
		} catch (Exception e1) {
			e1.printStackTrace();
		}

		if (!mIsUserSeekable || !isEnabled()) {
			return false;
		}

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			setPressed(true);
			onStartTrackingTouch();
			trackTouchEvent(event);
			break;

		case MotionEvent.ACTION_MOVE:
			trackTouchEvent(event);
			Method attemptClaimDrag;
			try {
				attemptClaimDrag = this.getClass().getSuperclass()
						.getDeclaredMethod("attemptClaimDrag");
				attemptClaimDrag.setAccessible(true);
				attemptClaimDrag.invoke(this);
			} catch (Exception e) {
				e.printStackTrace();
			}
			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;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		Log.i(TAG, "onkeydown keycode=" + keyCode);
		if (isEnabled()) {
			int progress = getProgress();
			switch (keyCode) {
			case KeyEvent.KEYCODE_DPAD_DOWN:
				if (progress <= 0)
					break;
				setProgress(progress - getKeyProgressIncrement());
				return true;

			case KeyEvent.KEYCODE_DPAD_UP:
				if (progress >= getMax())
					break;
				setProgress(progress + getKeyProgressIncrement());
				return true;
				//释放左右按键
			case KeyEvent.KEYCODE_DPAD_LEFT:
			case KeyEvent.KEYCODE_DPAD_RIGHT:
				return false;
			}
		}
		return super.onKeyDown(keyCode, event);
	}

	protected void trackTouchEvent(MotionEvent event) {

		final int height = getHeight();
		final int available = height - getPaddingLeft() - getPaddingRight();
		int y = (int) (height - event.getY());
		float scale;
		float progress = 0;
		if (y < getPaddingLeft()) {
			scale = 0.0f;
		} else if (y > height - getPaddingRight()) {
			scale = 1.0f;
		} else {
			scale = (float) (y - getPaddingLeft()) / (float) available;
			float mTouchProgressOffset = 0.0f;
			try {
				Field mTouchProgressOffset_f = this.getClass().getSuperclass()
						.getDeclaredField("mTouchProgressOffset");
				mTouchProgressOffset_f.setAccessible(true);
				mTouchProgressOffset = mTouchProgressOffset_f.getFloat(this);
			} catch (Exception e) {
				e.printStackTrace();
			}
			progress = mTouchProgressOffset;
		}

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

		try {
			Method setProgress = this.getClass().getSuperclass()
					.getSuperclass()
					.getDeclaredMethod("setProgress", int.class, boolean.class);
			setProgress.setAccessible(true);
			setProgress.invoke(this, (int) progress, true);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

2,使用:新建xml文件在用到的地方添加VerticalSeekBar

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <com.mktech.component.VerticalSeekBar
        android:id="@+id/verticalseekbar_voice"
        android:layout_width="5dp"
        android:layout_height="200dip"
        android:focusable="true"
        android:maxWidth="5dp"
        android:minWidth="5dp"
        android:progressDrawable="@xml/seekbar_style"
        android:thumb="@null"
        android:thumbOffset="10dp" />
    <!-- android:progressDrawable="@xml/progress" -->

</LinearLayout>

注意:补充一点,重写竖直的seekbar后对xml的布局支持不是太好,也不能居中,可能是因为seekbar是水平控件,对竖直的支持不是太好的缘故;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值