【发布时间】:2012-03-20 13:38:53
【问题描述】:
是否可以仅在移动拇指时才移动搜索栏。 现在,即使在手指触摸时,搜索栏也会移动 可绘制的。我们如何禁用搜索栏的移动 手指触摸progressdrawable?
谢谢。
【问题讨论】:
-
你在哪里能做到这一点?我有同样的问题需要紧急帮助
-
@Jay:你好,我和你有同样的问题,你找到了解决办法吗??如果您对此有解决方案,请与我们分享...
是否可以仅在移动拇指时才移动搜索栏。 现在,即使在手指触摸时,搜索栏也会移动 可绘制的。我们如何禁用搜索栏的移动 手指触摸progressdrawable?
谢谢。
【问题讨论】:
我发现Ravi's solution 的问题在于感人 和移动到当前拇指位置之外仍然会导致跳跃。
下面的类解决了这个问题,并用一个小的增量替换了触摸跳跃,就像使用箭头键一样。
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);
}
}
【讨论】:
覆盖搜索栏的OnTouchListener 并仅在MotionEvent 是移动事件时处理拇指上的移动。
event.getAction() == MotionEvent.ACTION_MOVE
更新:1
这样的事情会起作用,但问题是即使用户将拇指移动 2 个单位,搜索栏也会移动。而且你真的不应该停止这种行为,因为它会弄乱搜索栏。
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;
}
});
【讨论】:
Ravi 的解决方案很棒,我在下面做了一些重构:
两个目的:
getThumb()函数只能在API 16以上使用的问题。onStopTrackingTouch(),只会拖动拇指这是我的代码:
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);
}
}
【讨论】:
这是 awy 答案的 Kotlin 版本,需要注意的是,当您在可绘制对象之外点击时绝对不会发生任何移动。重点是您不希望用户能够跳过。
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.appcompat.widget.AppCompatSeekBar
class NoSkipSeekBar @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0
) : AppCompatSeekBar(context, attrs, defStyle) {
private var isDragging = false
private fun isWithinThumb(event: MotionEvent): Boolean {
return thumb.bounds.contains(event.x.toInt(), event.y.toInt())
}
override fun onTouchEvent(event: MotionEvent): Boolean {
if (!isEnabled || thumb == null) return super.onTouchEvent(event)
when (event.action) {
MotionEvent.ACTION_DOWN -> {
if (isWithinThumb(event)) {
isDragging = true
return super.onTouchEvent(event)
} else {
return true
}
}
MotionEvent.ACTION_UP -> {
isDragging = false
return when {
isWithinThumb(event) -> super.onTouchEvent(event)
else -> true
}
}
MotionEvent.ACTION_MOVE -> if (!isDragging) return true
MotionEvent.ACTION_CANCEL -> isDragging = false
}
return super.onTouchEvent(event)
}
}
【讨论】:
【讨论】: