Reputation: 18738
My onProgressChanged()-event doesn't get fired when I set the progress of a SeekBar programmatically, but it does get fired perfectly fine when I physically move the SeekBar slider.
I'd expect the event to fire when using setProgress() - the Android Developer Reference even states that:
public abstract void onProgressChanged (SeekBar seekBar, int progress, boolean fromUser)
Notification that the progress level has changed. Clients can use the fromUser parameter to distinguish user-initiated changes from those that occurred programmatically.
Some code snippets from my project:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
final SeekBar mySeekBar = ((SeekBar) findViewById(R.id.mySeekBar));
mySeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
// Do some stuff
}
}
}
@Override
protected void onResume() {
super.onResume();
final SeekBar mySeekBar = ((SeekBar) findViewById(R.id.mySeekBar));
mySeekBar.setProgress(someValue); // This SHOULD trigger onProgressChanged(), but it doesn't...
}
Upvotes: 8
Views: 16065
Reputation: 1232
You need to ensure the value has definitely changed, otherwise it won't be picked up. Put in 2 lines. The 1st not wanted. The 2nd desired.
seekbar.setProgress(7); // Necessary to force the change to desired
seekbar.setProgress(50); // Desired progress
Upvotes: 1
Reputation: 2402
My listener didn't fire because I was calling setProgress()
BEFORE setting the listener
Upvotes: 3
Reputation: 3608
The accepted answer didn't work for me because it stopped getting fired when the progress is set to 1 programmatically (which is the same bug).
What I did instead was to invoke the onProgressChanged() myself. I the seek bar is a member variable.
void setProgressValue(int progress){
if(progress == 0){ //the default progress is 0. if i set it to 0 again the call back wont be invoked
mSeekBar.setProgress(progress);
onProgressChanged(progress,mSeekBar,false);
}
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
//things to be done when the call back is received
}
Posting in the hope of helping someone later.
Upvotes: 0
Reputation: 1215
one possible workaround is to create own widget extending Seekbar and implementing two methods for your needs:
private OnSeekBarChangeListener onSeekBarChangeListener;
@Override
public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) {
super.setOnSeekBarChangeListener(l);
onSeekBarChangeListener = l;
}
@Override
public void setProgress(int progress) {
super.setProgress(progress);
if (onSeekBarChangeListener != null) {
onSeekBarChangeListener.onProgressChanged(this, progress, false);
}
}
Upvotes: 0
Reputation: 553
Set progress=10 in xml file as shown below:
<SeekBar android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="10"
android:max="100" />
Then in main file write below code:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
seekbar.setProgress(50)
}
}, 100);
Give delay less so that it doesn't affect the UI.
Upvotes: 1
Reputation: 8071
SeekBar.OnSeekBarChangeListener.onProgressChanged
is only called when the progress is actually changed, not necessarily when setProgress
is called - this only happens if the new progress is different from the last.
Looking at the source of SeekBar, which extends AbsSeekBar which in turn extends ProgressBar, we can see that a call to setProgress()
doesn't fire the onProgressChanged()
event unless the new progress is different from the previous one as seen in the source below.
/*
Snippet from ProgressBar.java
*/
public void setProgress(int progress, boolean animate) {
setProgressInternal(progress, false, animate);
}
synchronized boolean setProgressInternal(int progress, boolean fromUser, boolean animate) {
if (mIndeterminate) {
// Not applicable.
return false;
}
progress = MathUtils.constrain(progress, mMin, mMax);
if (progress == mProgress) {
// No change from current.
return false;
}
mProgress = progress;
refreshProgress(R.id.progress, mProgress, fromUser, animate);
return true;
}
Upvotes: 1
Reputation: 237
simply call
mySeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
int i= arg0.getProgress();
//youre seekbar.setProgress(i);
}
}
Upvotes: -1
Reputation: 4390
I can confirm with certainty that setProgress
works on Android version 6.0.1.
Another StackOverflow answer said it was a bug. If this was true, it is definitely no longer the case.
This code works on my test setup:
@Override
public void onResume() {
super.onResume();
SeekBar seekBar = (SeekBar)findViewById(R.id.seek_bar);
seekBar.setProgress(seekBar.getProgress());
}
As expected, the SeekBar
's OnSeekBarChangeListener
is getting called.
For troubleshooting, make sure that you set the listener properly using setOnSeekBarChangeListener()
and make sure you implement the interface functions.
Other SO answers seem to indicate that you should only call setProgress()
from the UI thread. This answer shows how that can be done.
Upvotes: -1
Reputation: 620
+1 for Romuald Brunet's answer:
Here was my "hack" to fix it:
<SeekBar android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="1"
android:max="200" />
Note the progress="1", set the default progress in the layout to 1, then in my code when I actually default it to 0, a change in the progress occurs and the onProgressChanged() event fires.
Upvotes: 6
Reputation: 5831
Stumbled across the same problem just now.
In my case, the onProgressChanged
did not get fired simply because the value did not actually change. I was setting the same value as the current one (0
:)
(and I don't see anything wrong with your code)
Upvotes: 9