Skip to content

Instantly share code, notes, and snippets.

@mobiRic
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mobiRic/c65a57a2a52c7f48f3db to your computer and use it in GitHub Desktop.
Save mobiRic/c65a57a2a52c7f48f3db to your computer and use it in GitHub Desktop.
Custom Android SeekBar that allows for easy increment / decrement by touch.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- CUSTOM SEEKBAR -->
<declare-styleable name="NoSkipSeekBar">
<attr name="keyProgressIncrement" format="integer" />
</declare-styleable>
</resources>
<lib.widget.NoSkipSeekBar
android:id="@+id/seekBarPercent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:keyProgressIncrement="10" />
package lib.widget;
import mobi.glowworm.example.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.widget.SeekBar;
/**
* NoSkipSeekBar is an extension of {@link SeekBar} that prevents jumps in position by touching
* outside the current thumb position. </p>
*
* Touches are replaced by an increment or decrement the same as would be achieved using a DPAD's
* Left or Right arrow keys. The amount to increment can be defined in XML using the custom
* <code>keyProgressIncrement</code> tag, or in code using {@link #setKeyProgressIncrement(int)}.
*/
public class NoSkipSeekBar extends SeekBar
{
/**
* <code>true</code> if the thumb is being dragged; <code>false</code> otherwise.
*/
private boolean isDragging;
public NoSkipSeekBar(Context context)
{
super(context);
}
public NoSkipSeekBar(Context context, AttributeSet attrs)
{
super(context, attrs);
if (!isInEditMode())
{
initXml(context, attrs);
}
}
public NoSkipSeekBar(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
if (!isInEditMode())
{
initXml(context, attrs);
}
}
private void initXml(Context context, AttributeSet attrs)
{
TypedArray a =
context.getTheme().obtainStyledAttributes(attrs, R.styleable.NoSkipSeekBar, 0, 0);
try
{
int keyProgressIncrement =
a.getInteger(R.styleable.NoSkipSeekBar_keyProgressIncrement, 1);
setKeyProgressIncrement(keyProgressIncrement);
}
finally
{
a.recycle();
}
}
/**
* Set the range of the progress bar to <code>0...max</code>. </p>
*
* Allows the key progress increment value to remain the same, or to be automatically updated as
* if {@link #setMax(int)} was used instead.
*/
public synchronized void setMax(int max, boolean autoUpdateKeyProgressIncrement)
{
int oldIncrement = getKeyProgressIncrement();
setMax(max);
if (!autoUpdateKeyProgressIncrement)
{
setKeyProgressIncrement(oldIncrement);
}
}
private boolean isWithinThumb(MotionEvent event)
{
return getThumb().getBounds().contains((int) event.getX(), (int) event.getY());
}
/**
* Increments or decrements the progress value, based on the sign of parameter.
*
* @param direction
* Set > 0 to increment; < 0 to decrement.
*/
private void increment(int direction)
{
if (direction != 0)
{
final KeyEvent key =
new KeyEvent(KeyEvent.ACTION_DOWN, (direction < 0 ? KeyEvent.KEYCODE_DPAD_LEFT
: KeyEvent.KEYCODE_DPAD_RIGHT));
onKeyDown(key.getKeyCode(), key);
}
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
if ((!isEnabled()) || (getThumb() == null))
{
return super.onTouchEvent(event);
}
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
if (!isWithinThumb(event))
{
return true;
}
isDragging = true;
break;
}
case MotionEvent.ACTION_UP:
{
if (!isDragging)
{
final Rect r = getThumb().getBounds();
increment((int) event.getX() - (r.left + r.right) / 2);
return true;
}
isDragging = false;
break;
}
case MotionEvent.ACTION_MOVE:
{
if (!isDragging)
{
return true;
}
break;
}
case MotionEvent.ACTION_CANCEL:
{
isDragging = false;
break;
}
}
return super.onTouchEvent(event);
}
}
@mobiRic
Copy link
Author

mobiRic commented Jun 30, 2014

Fixed occasional false increment after dragging thumbnail.

@mobiRic
Copy link
Author

mobiRic commented Jun 30, 2014

Add setMax() overload to allow key progress increment to remain the same when max is updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment