问题
Is it possible to have the seekbar move only when the thumb is moved. Right now the seekbar moves even on finger touch in the progressdrawable. How do we disable the movement of the seekbar on finger touch of the progressdrawable?
Thanks.
回答1:
Override the OnTouchListener for the seekbar and only process the movement on the thumb when the MotionEvent
is a move event.
event.getAction() == MotionEvent.ACTION_MOVE
Update : 1
Something like this will work but the catch is that even if the user moves the thumb 2 units the seekbar moves. And you should really not stop this behavior as it would mess the the seekbar.
seekBar.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_MOVE){
Log.d(TAG, "Moved , process data, Moved to :" + seekBar.getProgress());
seekBar.setProgress(seekBar.getProgress());
return false;
}
Log.d(TAG, "Touched , Progress :" + seekBar.getProgress());
return true;
}
});
回答2:
I found that the problem with Ravi's solution is that touching and moving outside of the current thumb position would still result in a jump.
The class below resolves that issue and replaces the jump-on-touch with a small increment, the same as one would get with arrow keys.
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.widget.SeekBar;
/**
* A NoSkipSeekBar is an extension of {@link SeekBar} that prevents jumps in position
* by touching outside the current thumb position. Such touches are replaced by
* an increment or decrement the same as would be achieved using a DPAD's Left or
* Right arrow keys.
*/
public class NoSkipSeekBar extends SeekBar {
public NoSkipSeekBar(Context context) {
super(context);
}
public NoSkipSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NoSkipSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
private boolean isDragging;
private boolean isWithinThumb(MotionEvent event) {
return getThumb().getBounds().contains((int)event.getX(), (int)event.getY());
}
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)) {
isDragging = true;
return super.onTouchEvent(event);
} else {
return true;
}
case MotionEvent.ACTION_UP:
isDragging = false;
if (isWithinThumb(event)) {
return super.onTouchEvent(event);
} else {
final Rect r = getThumb().getBounds();
increment((int)event.getX() - (r.left + r.right) / 2);
return true;
}
case MotionEvent.ACTION_MOVE:
if (!isDragging) return true;
break;
case MotionEvent.ACTION_CANCEL:
isDragging = false;
break;
}
return super.onTouchEvent(event);
}
}
回答3:
Ravi's solution is great, I did some refactoring below:
Two purposes:
- resolve the
getThumb()
function that only can use above the API 16 issues. - clicking the seekbar will not invoke the
onStopTrackingTouch()
but only drag the thumb
This is my code:
public class NoSkipSeekBar extends SeekBar {
Drawable mThumb;
@Override
public void setThumb(Drawable thumb) {
super.setThumb(thumb);
mThumb = thumb;
}
public Drawable getSeekBarThumb() {
return mThumb;
}
public NoSkipSeekBar(Context context) {
super(context);
}
public NoSkipSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NoSkipSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
private boolean isDragging;
private boolean isStart = false;
private boolean isWithinThumb(MotionEvent event) {
Rect rect = getSeekBarThumb().getBounds();//increate the thumb invoke area
Rect rect1 = new Rect();
rect1.left = rect.left - 50;
rect1.right = rect.right + 50;
rect1.bottom = rect.bottom + 50;
return rect1.contains((int)event.getX(), (int)event.getY());
}
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() || getSeekBarThumb() == null) return super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (isWithinThumb(event)) {
isDragging = true;
isStart = true;
return super.onTouchEvent(event);
} else {
return true;
}
case MotionEvent.ACTION_UP:
isDragging = false;
if(isStart){
isStart = false;
return super.onTouchEvent(event);
}
if (isWithinThumb(event)) {
return super.onTouchEvent(event);
} else {
//final Rect r = getThumb().getBounds();
//increment((int)event.getX() - (r.left + r.right) / 2);
return true;
}
case MotionEvent.ACTION_MOVE:
if (!isDragging) return true;
break;
case MotionEvent.ACTION_CANCEL:
isDragging = false;
break;
}
return super.onTouchEvent(event);
}
}
回答4:
Have you looked at this:
Really similar thread which should help you solve your question:
SeekBar's thumb only appears when touched
Best of luck
来源:https://stackoverflow.com/questions/9787906/android-seekbar-solution