我在Android应用中使用SeekBar
。当用户单击SeekBar
上的任意位置时,其进度值会发生变化。我只希望在用户滑动SeekBar
拇指时更改进度值(就像iOS中的UISlider
一样)。
我已尝试将clickable
的{{1}}属性设置为false,但这不起作用。我怎样才能达到预期的行为?
答案 0 :(得分:9)
本周我遇到了同样的问题,我使用自定义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;
}}
希望这有帮助
答案 1 :(得分:8)
查看另一个帖子:
User can not interact with the 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();
}
});
}
}
答案 2 :(得分:4)
现在为时已晚,但也许有人需要解决方案。我扩展自定义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);
}
}
}
答案 3 :(得分:1)
我想出了一个解决方案,它不是很漂亮,但应该可以解决这个问题......
以下是这个想法:
创建一个不可见的叠加层,覆盖除拇指按钮以外的所有滑块
(我使用黑色的搜索栏作为叠加层)
按下拇指时,在滑块上调用'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);
答案 4 :(得分: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;
}
}
}
您可以比较停止跟踪时的进度。
答案 5 :(得分:0)
查看@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:这是我的第一篇文章,抱歉,如果我做错了。
答案 6 :(得分:0)
这个与SeekBar中的事件监听器完美配合。
PS。我从Slim改进了这个代码,使其更加通用。
/**
* ProtectedSeekBar
* 01/27/15
*
* @author Jetsada Machom <jim@imjim.im>
*/
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);
}
}
答案 7 :(得分:0)
通过此代码,您可以禁用用户移动的拇指
SeekBar progress = (SeekBar) findViewById(R.id.timer);
seekBar.setProgress(time);
其中“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);
}
}
});
答案 8 :(得分: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
}
}
答案 9 :(得分: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);
}
}
显示触摸位置以说明我描述的行为。
答案 10 :(得分:0)
对于在seebBar上禁用单击,您可以在DOWN和UP事件之间观看时间,通常单击的持续时间小于100 ms。
<script type="application/javascript">
... ga setup here
<% if @ga_page.present? %>
ga('set', 'page', '<%= @ga_page%>');
<% end %>
ga('send', 'pageview');
</script>
答案 11 :(得分: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”表达式的内容,但这不能使代码可读。
答案 12 :(得分:0)
在此处查看答案。它仅允许通过拇指而不是可绘制进度来更改进度。 https://stackoverflow.com/a/62165116/1159930