12

SeekBar在我的 Android 应用程序中使用 a 。当用户单击 上的任意位置时SeekBar,其进度值会更改。我只希望在用户滑动拇指时更改进度值SeekBar(就像UISlideriOS 中的 a 一样)。

我尝试将 的clickable属性设置SeekBar为 false 但这没有用。我怎样才能达到预期的行为?

4

13 回答 13

10

本周我遇到了同样的问题,我使用自定义 SeekBar 解决了它:按照我的代码:

public class Slider extends SeekBar {

private Drawable mThumb;

public Slider(Context context) {
    super(context);

}

public Slider(Context context, AttributeSet attrs) {
    super(context, attrs);

}

@Override
public void setThumb(Drawable thumb) {
    super.setThumb(thumb);
    mThumb = thumb;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {

        if (event.getX() >= mThumb.getBounds().left
                && event.getX() <= mThumb.getBounds().right
                && event.getY() <= mThumb.getBounds().bottom
                && event.getY() >= mThumb.getBounds().top) {

            super.onTouchEvent(event);
        } else {
            return false;
        }
    } else if (event.getAction() == MotionEvent.ACTION_UP) {
        return false;
    } else {
        super.onTouchEvent(event);
    }

    return true;
}}

希望这可以帮助

于 2013-06-07T21:07:48.100 回答
8

看看这个其他线程:

用户无法与 Seekbar 交互

我尝试了以下方法,效果很好。请注意,我的 seekbar 的 android:max 属性设置为 100,如下所示:


<SeekBar
android:id="@+id/EnableBar"
android:layout_span="2"
android:max="100"
/>

package com.androidbook.hiworld;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.SeekBar;


public class HiWorldActivity extends Activity {
    int originalProgress;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        SeekBar seek = (SeekBar)findViewById(R.id.EnableBar);

        seek.setOnSeekBarChangeListener(
        new SeekBar.OnSeekBarChangeListener() {
           public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
               ((TextView)findViewById(R.id.SeekTxt)).setText("Value: "+progress);
               if(fromTouch == true){
                  // only allow changes by 1 up or down
                  if ((progress > (originalProgress+24))
                       || (progress < (originalProgress-24))) {
                     seekBar.setProgress( originalProgress);
                  } else {
                      originalProgress = progress;
                  }
               } 
           }

           @Override
           public void onStopTrackingTouch(SeekBar seekBar) {
               //Nothing here..                
           }

           @Override
           public void onStartTrackingTouch(SeekBar seekBar) {
               originalProgress = seekBar.getProgress();
           }
        });
    }
}
于 2011-08-01T22:01:38.197 回答
3

为时已晚,但也许有人需要解决方案。我扩展自定义 SeekBar 并覆盖 onTouchEvent。

package com.timera.android.common.view;

import android.content.Context;
import android.util.AttributeSet; 
import android.view.MotionEvent;
import android.widget.SeekBar;

public class OnlySeekableSeekBar extends SeekBar {

public OnlySeekableSeekBar(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

public OnlySeekableSeekBar(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public OnlySeekableSeekBar(Context context) {
    super(context);
}

@Override
public boolean onTouchEvent(MotionEvent event) {

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        final int width = getWidth();
        final int available = width - getPaddingLeft() - getPaddingRight();
        int x = (int) event.getX();
        float scale;
        float progress = 0;
        if (x < getPaddingLeft()) {
            scale = 0.0f;
        } else if (x > width - getPaddingRight()) {
            scale = 1.0f;
        } else {
            scale = (float) (x - getPaddingLeft()) / (float) available;
        }
        final int max = getMax();
        progress += scale * max;
        if (progress < 0) {
            progress = 0;
        } else if (progress > max) {
            progress = max;
        }

        if (Math.abs(progress - getProgress()) < 10)
            return super.onTouchEvent(event);
        else
            return false;
    default:
        return super.onTouchEvent(event);
    }
}
}
于 2013-11-28T14:07:31.380 回答
1

这与 SeekBar 中的事件侦听器完美配合。

PS。我从 Slim 改进了这段代码,使其更通用。

/**
 * ProtectedSeekBar
 * 01/27/15
 */
public class ProtectedSeekBar extends SeekBar {

    private Drawable mThumb;

    public ProtectedSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public ProtectedSeekBar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ProtectedSeekBar(Context context) {
        super(context);
    }

    @Override
    public void setThumb(Drawable thumb) {
        super.setThumb(thumb);
        mThumb = thumb;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN) {
            if( event.getX() < mThumb.getBounds().left ||
                event.getX() > mThumb.getBounds().right ||
                event.getY() > mThumb.getBounds().bottom ||
                event.getY() < mThumb.getBounds().top) {
                return false;
            }
        }
        return super.onTouchEvent(event);
    }
}
于 2015-01-27T15:31:01.543 回答
1

我想出了一个解决方案,它不是很漂亮,但它应该可以解决问题......

这是想法:

  1. 创建一个不可见的覆盖,将覆盖除拇指按钮之外的所有滑块

    (我使用了一个涂黑的搜索栏作为覆盖)

  2. 按下拇指时,调用滑块上的“bringToFront”方法

  3. 松开拇指时,在不可见的叠加层上调用“bringToFront”方法

请注意,要使其正常工作,您必须更改叠加层的大小,以便它覆盖除拇指按钮之外的所有内容(我建议使用两个叠加层[拇指按钮的每一侧各一个])

当您释放拇指按钮时,您应该调整叠加层的大小

......就像我说的,它不漂亮。我确信有更好的方法可以做到这一点,但如果你必须完成它,我会试试这个。

   yourBarChangeListener yourBarChangeListener = new SeekBar.OnSeekBarChangeListener() { 

    @Override 
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
     } 

    @Override 
    public void onStartTrackingTouch(SeekBar seekBar) {
     // YOUR CODE HERE 
    } 
    @Override 
    public void onStopTrackingTouch(SeekBar seekBar) { 
    } 
}; 
yourBar.setOnSeekBarChangeListener(yourBarChangeListener);
于 2011-04-22T19:08:15.920 回答
0

查看@lordmegamax 代码,我发现有些东西不起作用。

  1. int oldProgress 不能留在 onCreate 里面,你需要在外面声明它。
  2. 如果你 seekBar 总是从头开始, onStartTrackingTouch 将总是返回 0,所以你的 onStopTrackingTouch 永远不会工作。

稍微思考了一下,我找到了解决办法。

//SeekBar Slide
    skbLogin.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
        //Force Slide From Beginning
        public void onStartTrackingTouch(SeekBar seekBar) { continuosProgress = false; }
        //Execute when reach the max
        public void onStopTrackingTouch(SeekBar seekBar) {
            if(continuosProgress)
                if(seekBar.getProgress() == 100) btnLogin();
                else skbRollBack();
            else
                seekBar.setProgress(0);
        }
        //Check Slide from Beginning
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            if(progress < 10) continuosProgress = true;
        }
    });

希望能帮助到你。此致

PS:这是我的第一篇文章,如果我做错了,请见谅。

于 2013-04-26T17:52:31.270 回答
0
    int oldProgress;
    boolean isOn = true;
    vSeek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            oldProgress = seekBar.getProgress();
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            if (oldProgress == seekBar.getProgress()) {
                if (isOn) {
                    seekBar.setThumb(getResources().getDrawable(R.drawable.blck_btn));
                    isOn = false;
                } else {
                    seekBar.setThumb(getResources().getDrawable(R.drawable.blck_btn_selected));
                    isOn = true;
                }
            }
        }

您可以在停止跟踪时比较进度。

于 2013-02-26T18:24:32.203 回答
0

通过此代码,您可以禁用拇指按用户移动

     SeekBar progress = (SeekBar) findViewById(R.id.timer);
      seekBar.setProgress(time);

其中“时间”是一个整数变量并保存进度

     progress.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress,
                boolean fromUser) {
            if(fromUser){
                seekBar.setProgress(time);
            }

        }
    });
于 2015-04-09T13:10:46.960 回答
0

在这里查看答案。它只允许通过拇指而不是进度可绘制来更改进度。 https://stackoverflow.com/a/62165116/1159930

于 2020-06-03T04:20:05.323 回答
0

要禁用 seebBar 上的单击,您可以查看 DOWN 和 UP 事件之间的时间,通常单击的持续时间小于 100 毫秒。

seekBar.setOnTouchListener(new View.OnTouchListener() {
      private long startTime = 0;
      private long endTime = 0;

      @Override
      public boolean onTouch(View view, MotionEvent motionEvent) {

        if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
          startTime = motionEvent.getEventTime();
          return true;
        }
        if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
          endTime = motionEvent.getEventTime();
          if (Math.abs(startTime-endTime)<=100)
            return true;
          else
            return false;
        }
        Log.d(TAG, String.valueOf(motionEvent.getEventTime()));
        return false;
      }
    });
于 2017-09-22T12:51:47.407 回答
0

我还没有看到建议的另一个选项:转换接收到的运动事件的子类,以使每个手势看起来都从拇指的中心开始。这对底层的搜索栏行为有以下影响:

  • 在适当位置敲击不会产生拇指移动(与其他建议的解决方案相同);
  • 执行从拇指开始的滑动手势仍然可以平滑地平移拇指(与其他建议的解决方案不同)。

代码

/**
 * Translates every gesture to be centered at the current thumb location.
 */
public final class ThumbCentricSeekBar extends SeekBar {

    // Constructors go here...

    private Float offsetX;
    private Float offsetY;

    @Override
    public boolean onTouchEvent(final MotionEvent event) {
        if (event.getAction() == ACTION_DOWN && offsetX == null) {
            offsetX = getThumb().getBounds().centerX() - event.getX();
            offsetY = getThumb().getBounds().centerY() - event.getY();
        }

        event.offsetLocation(offsetX, offsetY);

        if (event.getAction() == ACTION_UP) {
            offsetX = null;
            offsetY = null;
        }

        return super.onTouchEvent(event);
    }

}

演示

显示触摸位置以说明我描述的行为。

在此处输入图像描述

于 2017-03-02T20:16:51.047 回答
0
private class UpdateListener implements OnSeekBarChangeListener {

    // max step user can change at once
    private static final int THUMB_MAX_MOVE = 5;

    // current seekbar value (50 is initial seekbar value as defined in xml)
    private int currentProgress = 50;

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

        // save current value before user jumps around
        currentProgress = seekBar.getProgress();
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {}

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

        // check if we've jumped too far
        if (Math.abs(currentProgress - progress) > THUMB_MAX_MOVE) {

            // if so, revert to last progress and return
            seekBar.setProgress(currentProgress);
            return;
        }

        // if not, move was valid and update current progress
        currentProgress = progress;

        // do anything more here
    }
}
于 2016-05-17T05:19:50.570 回答
0

我面临的情况是 SeekBar 是由另一段代码创建的,因此我无法使用 onTouchEvent() 处理程序创建子类。相反,我为我想弄乱的实例覆盖了 OnTouchListener ...

SeekBar sb = (SeekBar) findViewById(R.id.seekbar);

sb.setOnTouchListener(new OnTouchListener()
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Drawable thumb = ((SeekBar) v).getThumb();

        if (   event.getX() < thumb.getBounds().left
            || event.getX() > thumb.getBounds().right
            || event.getY() < thumb.getBounds().top
            || event.getY() > thumb.getBounds().bottom) {
            // event occurred outside the thumb slider so ignore it
            return true;
        } else {
            // event occurred inside the thumb slider so pass it on
            return false;
        }
    }
});

是的,我可以简单地返回“if”表达式的内容,但这不会使代码可读。

于 2018-11-21T15:10:31.720 回答