onProgressChanged() of a SeekBar is called twice

yadav_vi picture yadav_vi · Aug 14, 2014 · Viewed 8.9k times · Source

I have created a Custom SeekBarPreference such that it displays a range of time to be selected from (say 0.2 sec to 2.2 sec). My problem is onProgressChanged() is called twice - once with progress = 0 and the second time with progress = "actual value". I am storing the value in a SharedPreference so that I can use it later in my application.
Here is my code snippet -

@Override
protected View onCreateDialogView() {
    LayoutInflater inflator = ((PreferenceActivity) mContext)
            .getLayoutInflater();
    View view = inflator.inflate(R.layout.seek_bar, null);

    mCurrentValue = PreferenceManager.getDefaultSharedPreferences(mContext)
            .getFloat(this.getKey(), mDefaultValue);
    ......
    SeekBar mSeekBar = (SeekBar) view.findViewById(R.id.seekbar);
    mSeekBar.setOnSeekBarChangeListener(this);

    mSeekBar.setMax(20);
    mSeekBar.setProgress((int) ((mCurrentValue - mMinValue)
            / (mMaxValue - mMinValue) * 20)); // 20 = progress bar max value.
    return view;
}

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
        boolean fromUser) {
    if (progress != 0) {
        mCurrentValue = (float) ((float) progress / 20
                * (mMaxValue - mMinValue) + mMinValue);
    }
    mValueText.setText(Float.toString(mCurrentValue)); 
    /* mValueText is a TextBox where I display my Current Value */
}

Here, I have checked the value of progress such that it is not equal to 0 and hence it avoids the first call. However, the side-effect of this is that I am not able to set anything to 0.

What can be the work around for this?

Answer

yadav_vi picture yadav_vi · Aug 22, 2014

The callback method onProgressChanged() has a boolean parameter fromUser.
Using this parameter we can determine if the changes are coming from the Framework or are made by the User himself.

Thus, an implementation like -

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
        boolean fromUser) {
    if (fromUser) { // If the changes are from the User only then accept the
                    // changes
    /* Instead of -> if (progress != 0) { */

        mCurrentValue = (float) ((float) progress / 20
                * (mMaxValue - mMinValue) + mMinValue);
        mCurrentValue *= 10;
        mCurrentValue = Math.round(mCurrentValue);
        mCurrentValue /= 10;
    }

    mValueText.setText(Float.toString(mCurrentValue));
}

sets the value of TextView only when it is changed by the User.