我SeekBar
在我的 Android 应用程序中使用 a 。当用户单击 上的任意位置时SeekBar
,其进度值会更改。我只希望在用户滑动拇指时更改进度值SeekBar
(就像UISlider
iOS 中的 a 一样)。
我尝试将 的clickable
属性设置SeekBar
为 false 但这没有用。我怎样才能达到预期的行为?
我SeekBar
在我的 Android 应用程序中使用 a 。当用户单击 上的任意位置时SeekBar
,其进度值会更改。我只希望在用户滑动拇指时更改进度值SeekBar
(就像UISlider
iOS 中的 a 一样)。
我尝试将 的clickable
属性设置SeekBar
为 false 但这没有用。我怎样才能达到预期的行为?
本周我遇到了同样的问题,我使用自定义 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;
}}
希望这可以帮助
看看这个其他线程:
我尝试了以下方法,效果很好。请注意,我的 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();
}
});
}
}
为时已晚,但也许有人需要解决方案。我扩展自定义 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);
}
}
}
这与 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);
}
}
我想出了一个解决方案,它不是很漂亮,但它应该可以解决问题......
这是想法:
创建一个不可见的覆盖,将覆盖除拇指按钮之外的所有滑块
(我使用了一个涂黑的搜索栏作为覆盖)
按下拇指时,调用滑块上的“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);
查看@lordmegamax 代码,我发现有些东西不起作用。
稍微思考了一下,我找到了解决办法。
//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:这是我的第一篇文章,如果我做错了,请见谅。
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;
}
}
}
您可以在停止跟踪时比较进度。
通过此代码,您可以禁用拇指按用户移动
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);
}
}
});
在这里查看答案。它只允许通过拇指而不是进度可绘制来更改进度。 https://stackoverflow.com/a/62165116/1159930
要禁用 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;
}
});
我还没有看到建议的另一个选项:转换接收到的运动事件的子类,以使每个手势看起来都从拇指的中心开始。这对底层的搜索栏行为有以下影响:
/**
* 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);
}
}
显示触摸位置以说明我描述的行为。
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
}
}
我面临的情况是 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”表达式的内容,但这不会使代码可读。