package com.edmodo.rangebar;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
public class TickedSeekBar extends RangeBar{
private Bar mBar;
private Thumb mThumb;
private int mIndex;
private TickedSeekBar.OnTickChangeListener mListener;
public TickedSeekBar(Context context) {
super(context);
}
public TickedSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
tickedSeekBarInit(context, attrs);
}
public TickedSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
tickedSeekBarInit(context, attrs);
}
// View Methods ////////////////////////////////////////////////////////////
@Override
public Parcelable onSaveInstanceState() {
final Bundle bundle = new Bundle();
bundle.putParcelable("RangeBar",super.onSaveInstanceState());
bundle.putInt("TICK_INDEX", mIndex);
return bundle;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
final Bundle bundle = (Bundle) state;
super.onRestoreInstanceState(bundle.getParcelable("RangeBar"));
mIndex = bundle.getInt("TICK_INDEX");
setThumbIndex(mIndex);
} else {
super.onRestoreInstanceState(state);
}
}
@Override
protected float getMarginLeft() {
return ((mThumb != null) ? mThumb.getHalfWidth() : 0);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
final Context ctx = getContext();
// This is the initial point at which we know the size of the View.
// Create the two thumb objects.
final float yPos = h / 2f;
mThumb = new Thumb(ctx,
yPos,
mThumbColorNormal,
mThumbColorPressed,
mThumbRadiusDP,
mThumbImageNormal,
mThumbImagePressed);
// Create the underlying bar.
final float marginLeft = mThumb.getHalfWidth();
final float barLength = w - 2 * marginLeft;
mBar = new Bar(ctx, marginLeft, yPos, barLength, mTickCount, mTickHeightDP, mBarWeight, mBarColor);
// Initialize thumbs to the desired indices
mThumb.setX(marginLeft + (mIndex / (float) (mTickCount - 1)) * barLength);
// Set the thumb indices.
final int newIndex = mBar.getNearestTickIndex(mThumb);
// Call the listener.
if (newIndex != mIndex) {
mIndex = newIndex;
if (mListener != null) {
mListener.onIndexChangeListener(this, mIndex);
}
}
// Create the line connecting the two thumbs.
mConnectingLine = new ConnectingLine(ctx, yPos, mConnectingLineWeight, mConnectingLineColor);
}
@Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
mBar.draw(canvas);
mConnectingLine.draw(canvas, mLeftThumb, mThumb);
mThumb.draw(canvas);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// If this View is not enabled, don't allow for touch interactions.
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
onActionDown(event.getX(), event.getY());
return true;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
this.getParent().requestDisallowInterceptTouchEvent(false);
onActionUp(event.getX(), event.getY());
return true;
case MotionEvent.ACTION_MOVE:
onActionMove(event.getX());
this.getParent().requestDisallowInterceptTouchEvent(true);
return true;
default:
return false;
}
}
public void OnTickChangeListener(TickedSeekBar.OnTickChangeListener listener) {
mListener = listener;
}
public int getIndex() {
return mIndex;
}
public void setThumbIndex(int thumbIndex)
{
if (indexOutOfRange(thumbIndex, thumbIndex)) {
throw new IllegalArgumentException("A thumb index is out of bounds. Check that it is between 0 and mTickCount - 1");
} else {
if (mFirstSetTickCount == true)
mFirstSetTickCount = false;
mIndex = thumbIndex;
createThumb();
if (mListener != null) {
mListener.onIndexChangeListener(this, mIndex);
}
}
invalidate();
requestLayout();
}
private void tickedSeekBarInit(Context context, AttributeSet attrs)
{
mIndex = 0;
if (mListener != null) {
mListener.onIndexChangeListener(this, mIndex);
}
createThumb();
}
private void createThumb() {
Context ctx = getContext();
float yPos = getYPos();
mThumb = new Thumb(ctx,
yPos,
mThumbColorNormal,
mThumbColorPressed,
mThumbRadiusDP,
mThumbImageNormal,
mThumbImagePressed);
float marginLeft = getMarginLeft();
float barLength = getBarLength();
// Initialize thumbs to the desired indices
mThumb.setX(marginLeft + (mIndex / (float) (mTickCount - 1)) * barLength);
invalidate();
}
/**
* Handles a {@link MotionEvent#ACTION_DOWN} event.
*
* @param x the x-coordinate of the down action
* @param y the y-coordinate of the down action
*/
private void onActionDown(float x, float y) {
if (!mThumb.isPressed() && mThumb.isInTargetZone(x, y)) {
pressThumb(mThumb);
}
}
/**
* Handles a {@link MotionEvent#ACTION_UP} or
* {@link MotionEvent#ACTION_CANCEL} event.
*
* @param x the x-coordinate of the up action
* @param y the y-coordinate of the up action
*/
private void onActionUp(float x, float y) {
if (mThumb.isPressed()) {
releaseThumb(mThumb);
} else {
float thumbXDistance = Math.abs(mThumb.getX() - x);
// Get the updated nearest tick marks for thumb.
final int newIndex = mBar.getNearestTickIndex(mThumb);
if (newIndex != mIndex) {
mIndex = newIndex;
if (mListener != null) {
mListener.onIndexChangeListener(this, mIndex);
}
}
}
}
/**
* Handles a {@link MotionEvent#ACTION_MOVE} event.
*
* @param x the x-coordinate of the move event
*/
private void onActionMove(float x) {
// Move the pressed thumb to the new x-position.
if (mThumb.isPressed()) {
moveThumb(mThumb, x);
}
// Get the updated nearest tick marks for each thumb.
final int newIndex = mBar.getNearestTickIndex(mThumb);
// If either of the indices have changed, update and call the listener.
if (newIndex != mIndex) {
mIndex = newIndex;
if (mListener != null) {
mListener.onIndexChangeListener(this, mIndex);
}
}
}
// Inner Classes ///////////////////////////////////////////////////////////
/**
* A callback that notifies clients when the TickedSeekBar has changed. The
* listener will only be called when the thumb's index has changed - not
* for every movement of the thumb.
*/
public static interface OnTickChangeListener {
public void onIndexChangeListener(TickedSeekBar seekBar, int thumbIndex);
}
}