【问题标题】:Android seekbar solution安卓搜索栏解决方案
【发布时间】:2012-03-20 13:38:53
【问题描述】:

是否可以仅在移动拇指时才移动搜索栏。 现在,即使在手指触摸时,搜索栏也会移动 可绘制的。我们如何禁用搜索栏的移动 手指触摸progressdrawable?

谢谢。

【问题讨论】:

  • 你在哪里能做到这一点?我有同样的问题需要紧急帮助
  • @Jay:你好,我和你有同样的问题,你找到了解决办法吗??如果您对此有解决方案,请与我们分享...

标签: android seekbar


【解决方案1】:

我发现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);
    }
}

【讨论】:

  • 谢谢它帮助了我,这看起来像是一个解决方案,而不是像接受的答案那样的临时解决方法,为此 +1
【解决方案2】:

覆盖搜索栏的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;
            }
        });

【讨论】:

  • 嗨,它对我有点用处。但是当我点击搜索栏时,进度正在增加,没有移动或触摸拇指。你能给我完整的细节吗?
  • 听听这里到底发生了什么......当我触摸搜索栏时,它会自动进行而不用触摸或移动拇指......我只想在触摸 n 移动拇指时继续它......
  • 这里检查条件 n 之后是否也返回 true
  • 如果我只是在没有移动拇指的情况下触摸搜索栏,它会检测到motionevent..这是错误的..
【解决方案3】:

Ravi 的解决方案很棒,我在下面做了一些重构:

两个目的:

  1. 解决了getThumb()函数只能在API 16以上使用的问题。
  2. 点击搜索栏不会调用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);
    }
}

【讨论】:

    【解决方案4】:

    这是 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)
        }
    }
    

    【讨论】:

      【解决方案5】:

      你看过这个吗:

      非常相似的线程应该可以帮助您解决问题:

      SeekBar's thumb only appears when touched

      祝你好运

      【讨论】:

      • 您好,我不想让拇指消失,我只想禁用陷印事件.. 用户无法触摸搜索栏 n 增加进度。只有当我移动拇指时才能增加进度。谢谢
      • 现在发生了什么?当我在没有触摸 n 移动到拇指的情况下单击搜索栏的任何区域时,拇指会自动移动,这对我来说是错误的..用户只能在拇指上触摸 n 移动。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-20
      • 1970-01-01
      • 2013-12-07
      相关资源
      最近更新 更多