我在Android应用中使用了一个SeekBar
。当用户在SeekBar
上单击任何位置时,进度值会改变。我希望只有在用户滑动SeekBar
的滑块时才会改变进度值(就像iOS中的UISlider
一样)。
我尝试将SeekBar
的clickable
属性设置为false,但没有起作用。我该如何实现所需的行为?
我在Android应用中使用了一个SeekBar
。当用户在SeekBar
上单击任何位置时,进度值会改变。我希望只有在用户滑动SeekBar
的滑块时才会改变进度值(就像iOS中的UISlider
一样)。
我尝试将SeekBar
的clickable
属性设置为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);
}
}
}
/**
* 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);
}
}
SeekBar.getThumb
在 API >= 16 中已经公开。因此,如果您不需要向后兼容性,则可以删除该方法。 - zinuzoid我想到了一个解决方案,虽然不是很美观,但应该能解决问题...
这是我的想法:
创建一个无形的覆盖层,覆盖滑块除拇指按钮外的所有部分
(我使用了一个黑色的 seekbar 作为覆盖层)
当按下拇指时,在滑块上调用 '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);
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);
}
}
});
如果要禁用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;
}
});
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”表达式的内容,但这并不会使代码易读。
看了一下@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;
}
});