Android SeekBarPreference

19,577

The problem with sliding here is due to notifyChange() call. That is interfering with the sliding somehow. I am also working on similar widget because I do not like the Dialog approach.

As promised here is the solution that I added to my open source project:

I have written a SeekBarPreference class that is embeded widget inside the preferences activity instead of popup dialog. You can download the jar file from:

http://aniqroid.sileria.com/

The class documentation and usage is here: http://aniqroid.sileria.com/doc/api/com/sileria/android/view/SeekBarPreference.html

Also do not forget to checkout the handy companion class to auto show a summary when you change the SeekBar: http://aniqroid.sileria.com/doc/api/com/sileria/android/event/PrefsSeekBarListener.html

Share:
19,577
Lovro Pandžić
Author by

Lovro Pandžić

Updated on June 11, 2022

Comments

  • Lovro Pandžić
    Lovro Pandžić almost 2 years

    I'm currently trying to implement SeekBarPreference class using http://android-journey.blogspot.com/2010/01/for-almost-any-application-we-need-to.html tutorial with RelativeLayout. First problem is TextView preferenceText isn't showing at all. Second problem is the bar can't be slided like those in regular preferences (like media volume bar)?

    public class SeekBarPreference extends Preference implements
        OnSeekBarChangeListener {
    
    public static int maximum    = 100;
    public static int interval   = 5;
    private float oldValue = 25;
    private TextView Indicator;
    
    public SeekBarPreference(Context context) {
        super(context);
    }
    
    public SeekBarPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    
    @Override
    protected View onCreateView(ViewGroup parent) {
    
        float scale = getContext().getResources().getDisplayMetrics().density;
    
        RelativeLayout layout = new RelativeLayout(getContext());
    
        RelativeLayout.LayoutParams textParams = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT);
    
        RelativeLayout.LayoutParams sbarParams = new RelativeLayout.LayoutParams(
                Math.round(scale * 160),
                RelativeLayout.LayoutParams.WRAP_CONTENT);
    
        RelativeLayout.LayoutParams indParams = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT);
    
        TextView preferenceText = new TextView(getContext());
        preferenceText.setId(0);
        preferenceText.setText(getTitle());
        preferenceText.setTextSize(18);
        preferenceText.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD);
    
    
        SeekBar sbar = new SeekBar(getContext());
        sbar.setId(1);
        sbar.setMax(maximum);
        sbar.setProgress((int)this.oldValue);
        sbar.setOnSeekBarChangeListener(this);
    
        this.Indicator = new TextView(getContext());
        this.Indicator.setTextSize(12);
        this.Indicator.setTypeface(Typeface.MONOSPACE, Typeface.ITALIC);
        this.Indicator.setText("" + sbar.getProgress());
    
        textParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        sbarParams.addRule(RelativeLayout.RIGHT_OF, preferenceText.getId());
        indParams.setMargins(Math.round(20*scale), 0, 0, 0);
        indParams.addRule(RelativeLayout.RIGHT_OF, sbar.getId());
    
        preferenceText.setLayoutParams(textParams);
        sbar.setLayoutParams(sbarParams);
        this.Indicator.setLayoutParams(indParams);
        layout.addView(preferenceText);
        layout.addView(this.Indicator);
        layout.addView(sbar);
        layout.setId(android.R.id.widget_frame);
    
        return layout;
    }
    
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress,
            boolean fromUser) {
        progress = Math.round(((float) progress)/interval) * interval;
    
        if(!callChangeListener(progress)) {
            seekBar.setProgress((int) this.oldValue);
            return;
        }
    
        seekBar.setProgress(progress);
        this.oldValue = progress;
        this.Indicator.setText("" + progress);
        updatePreference(progress);
    
        notifyChanged();
    }
    
    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }
    
    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }
    
    @Override
    protected Object onGetDefaultValue(TypedArray ta, int index) {
        int dValue = ta.getInt(index, 25);
    
        return validateValue(dValue);
    }
    
    @Override
    protected void onSetInitialValue(boolean restoreValue,
            Object defaultValue) {
        int temp = restoreValue ? getPersistedInt(25) : (Integer)defaultValue;
        if(!restoreValue)
            persistInt(temp);
    
        this.oldValue = temp;
    }
    
    private int validateValue(int value) {
        if(value > maximum) 
            value = maximum;
        else if (value < 0)
            value = 0;
        else if (value % interval != 0)
            value = Math.round(((float) value)/interval) * interval;
    
        return value;
    }
    
    private void updatePreference(int newValue) {
        SharedPreferences.Editor editor = getEditor();
        editor.putInt(getKey(), newValue);
        editor.commit();
    }
    

    }