All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.WazaBe.HoloEverywhere.widget.AbsSeekBar Maven / Gradle / Ivy

The newest version!
package com.WazaBe.HoloEverywhere.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;

import com.WazaBe.HoloEverywhere.R;

public abstract class AbsSeekBar extends ProgressBar {
	private static final int NO_ALPHA = 0xFF;
	private float mDisabledAlpha;
	private boolean mIsDragging;
	boolean mIsUserSeekable = true;
	private int mKeyProgressIncrement = 1;
	private int mScaledTouchSlop;
	private Drawable mThumb;
	private int mThumbOffset;
	private float mTouchDownX;
	float mTouchProgressOffset;

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

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

	public AbsSeekBar(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		TypedArray a = context.obtainStyledAttributes(attrs,
				R.styleable.SeekBar, defStyle, 0);
		Drawable thumb = a.getDrawable(R.styleable.SeekBar_android_thumb);
		setThumb(thumb);
		int thumbOffset = a.getDimensionPixelOffset(
				R.styleable.SeekBar_android_thumbOffset, getThumbOffset());
		setThumbOffset(thumbOffset);
		mDisabledAlpha = a.getFloat(R.styleable.SeekBar_android_disabledAlpha,
				0.5f);
		a.recycle();
		mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
	}

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

	@Override
	protected void drawableStateChanged() {
		super.drawableStateChanged();
		Drawable progressDrawable = getProgressDrawable();
		if (progressDrawable != null) {
			progressDrawable.setAlpha(isEnabled() ? AbsSeekBar.NO_ALPHA
					: (int) (AbsSeekBar.NO_ALPHA * mDisabledAlpha));
		}
		if (mThumb != null && mThumb.isStateful()) {
			int[] state = getDrawableState();
			mThumb.setState(state);
		}
	}

	public int getKeyProgressIncrement() {
		return mKeyProgressIncrement;
	}

	public Drawable getThumb() {
		return mThumb;
	}

	public int getThumbOffset() {
		return mThumbOffset;
	}

	public boolean isInScrollingContainer() {
		return false;
	}

	@Override
	@SuppressLint("NewApi")
	public void jumpDrawablesToCurrentState() {
		super.jumpDrawablesToCurrentState();
		if (mThumb != null) {
			mThumb.jumpToCurrentState();
		}
	}

	@Override
	protected synchronized void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (mThumb != null) {
			canvas.save();
			canvas.translate(getPaddingLeft() - mThumbOffset, getPaddingTop());
			mThumb.draw(canvas);
			canvas.restore();
		}
	}

	@Override
	@SuppressLint("NewApi")
	public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
		super.onInitializeAccessibilityEvent(event);
		event.setClassName(AbsSeekBar.class.getName());
	}

	@Override
	@SuppressLint("NewApi")
	public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
		super.onInitializeAccessibilityNodeInfo(info);
		info.setClassName(AbsSeekBar.class.getName());
		if (isEnabled()) {
			final int progress = getProgress();
			if (progress > 0) {
				info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
			}
			if (progress < getMax()) {
				info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
			}
		}
	}

	void onKeyChange() {
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (isEnabled()) {
			int progress = getProgress();
			switch (keyCode) {
			case KeyEvent.KEYCODE_DPAD_LEFT:
				if (progress <= 0) {
					break;
				}
				setProgress(progress - mKeyProgressIncrement, true);
				onKeyChange();
				return true;
			case KeyEvent.KEYCODE_DPAD_RIGHT:
				if (progress >= getMax()) {
					break;
				}
				setProgress(progress + mKeyProgressIncrement, true);
				onKeyChange();
				return true;
			}
		}
		return super.onKeyDown(keyCode, event);
	}

	@Override
	protected synchronized void onMeasure(int widthMeasureSpec,
			int heightMeasureSpec) {
		Drawable d = getCurrentDrawable();
		int thumbHeight = mThumb == null ? 0 : mThumb.getIntrinsicHeight();
		int dw = 0;
		int dh = 0;
		if (d != null) {
			dw = Math
					.max(mMinWidth, Math.min(mMaxWidth, d.getIntrinsicWidth()));
			dh = Math.max(mMinHeight,
					Math.min(mMaxHeight, d.getIntrinsicHeight()));
			dh = Math.max(thumbHeight, dh);
		}
		dw += getPaddingLeft() + getPaddingRight();
		dh += getPaddingTop() + getPaddingBottom();
		setMeasuredDimension(
				View.supportResolveSizeAndState(dw, widthMeasureSpec, 0),
				View.supportResolveSizeAndState(dh, heightMeasureSpec, 0));
	}

	@Override
	public void onProgressRefresh(float scale, boolean fromUser) {
		super.onProgressRefresh(scale, fromUser);
		Drawable thumb = mThumb;
		if (thumb != null) {
			setThumbPos(getWidth(), thumb, scale, Integer.MIN_VALUE);
			invalidate();
		}
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		updateThumbPos(w, h);
	}

	void onStartTrackingTouch() {
		mIsDragging = true;
	}

	void onStopTrackingTouch() {
		mIsDragging = false;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (!mIsUserSeekable || !isEnabled()) {
			return false;
		}
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			if (isInScrollingContainer()) {
				mTouchDownX = event.getX();
			} else {
				setPressed(true);
				if (mThumb != null) {
					invalidate(mThumb.getBounds());
				}
				onStartTrackingTouch();
				trackTouchEvent(event);
				attemptClaimDrag();
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if (mIsDragging) {
				trackTouchEvent(event);
			} else {
				final float x = event.getX();
				if (Math.abs(x - mTouchDownX) > mScaledTouchSlop) {
					setPressed(true);
					if (mThumb != null) {
						invalidate(mThumb.getBounds());
					}
					onStartTrackingTouch();
					trackTouchEvent(event);
					attemptClaimDrag();
				}
			}
			break;
		case MotionEvent.ACTION_UP:
			if (mIsDragging) {
				trackTouchEvent(event);
				onStopTrackingTouch();
				setPressed(false);
			} else {
				onStartTrackingTouch();
				trackTouchEvent(event);
				onStopTrackingTouch();
			}
			invalidate();
			break;
		case MotionEvent.ACTION_CANCEL:
			if (mIsDragging) {
				onStopTrackingTouch();
				setPressed(false);
			}
			invalidate();
			break;
		}
		return true;
	}

	@Override
	public boolean performAccessibilityAction(int action, Bundle arguments) {
		if (super.performAccessibilityAction(action, arguments)) {
			return true;
		}
		if (!isEnabled()) {
			return false;
		}
		final int progress = getProgress();
		final int increment = Math.max(1, Math.round((float) getMax() / 5));
		switch (action) {
		case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
			if (progress <= 0) {
				return false;
			}
			setProgress(progress - increment, true);
			onKeyChange();
			return true;
		}
		case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
			if (progress >= getMax()) {
				return false;
			}
			setProgress(progress + increment, true);
			onKeyChange();
			return true;
		}
		}
		return false;
	}

	public void setKeyProgressIncrement(int increment) {
		mKeyProgressIncrement = increment < 0 ? -increment : increment;
	}

	@Override
	public synchronized void setMax(int max) {
		super.setMax(max);
		if (mKeyProgressIncrement == 0 || getMax() / mKeyProgressIncrement > 20) {
			setKeyProgressIncrement(Math.max(1,
					Math.round((float) getMax() / 20)));
		}
	}

	public void setThumb(Drawable thumb) {
		boolean needUpdate;
		if (mThumb != null && thumb != mThumb) {
			mThumb.setCallback(null);
			needUpdate = true;
		} else {
			needUpdate = false;
		}
		if (thumb != null) {
			thumb.setCallback(this);
			mThumbOffset = thumb.getIntrinsicWidth() / 2;
			if (needUpdate
					&& (thumb.getIntrinsicWidth() != mThumb.getIntrinsicWidth() || thumb
							.getIntrinsicHeight() != mThumb
							.getIntrinsicHeight())) {
				requestLayout();
			}
		}
		mThumb = thumb;
		invalidate();
		if (needUpdate) {
			updateThumbPos(getWidth(), getHeight());
			if (thumb != null && thumb.isStateful()) {
				int[] state = getDrawableState();
				thumb.setState(state);
			}
		}
	}

	public void setThumbOffset(int thumbOffset) {
		mThumbOffset = thumbOffset;
		invalidate();
	}

	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;
		available += mThumbOffset * 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);
	}

	private void trackTouchEvent(MotionEvent event) {
		final int width = getWidth();
		final int available = width - getPaddingLeft() - getPaddingRight();
		int x = (int) event.getX();
		float scale;
		float progress = 0;
		if (x < getPaddingLeft()) {
			scale = 0.0f;
		} else if (x > width - getPaddingRight()) {
			scale = 1.0f;
		} else {
			scale = (float) (x - getPaddingLeft()) / (float) available;
			progress = mTouchProgressOffset;
		}
		final int max = getMax();
		progress += scale * max;
		setProgress((int) progress, true);
	}

	private void updateThumbPos(int w, int h) {
		Drawable d = getCurrentDrawable();
		Drawable thumb = mThumb;
		int thumbHeight = thumb == null ? 0 : thumb.getIntrinsicHeight();
		int trackHeight = Math.min(mMaxHeight, h - getPaddingTop()
				- getPaddingBottom());
		int max = getMax();
		float scale = max > 0 ? (float) getProgress() / (float) max : 0;
		if (thumbHeight > trackHeight) {
			if (thumb != null) {
				setThumbPos(w, thumb, scale, 0);
			}
			int gapForCenteringTrack = (thumbHeight - trackHeight) / 2;
			if (d != null) {
				d.setBounds(0, gapForCenteringTrack, w - getPaddingRight()
						- getPaddingLeft(), h - getPaddingBottom()
						- gapForCenteringTrack - getPaddingTop());
			}
		} else {
			if (d != null) {
				d.setBounds(0, 0, w - getPaddingRight() - getPaddingLeft(), h
						- getPaddingBottom() - getPaddingTop());
			}
			int gap = (trackHeight - thumbHeight) / 2;
			if (thumb != null) {
				setThumbPos(w, thumb, scale, gap);
			}
		}
	}

	@Override
	protected boolean verifyDrawable(Drawable who) {
		return who == mThumb || super.verifyDrawable(who);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy