Autore Topic: Custom Preference - Dialog con SeekBar & SharedPreferences  (Letto 967 volte)

Offline funcool

  • Nuovo arrivato
  • *
  • Post: 42
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Acer Liquid CM 7.1
  • Play Store ID:
    elcasa
  • Sistema operativo:
    Windows 8
Custom Preference - Dialog con SeekBar & SharedPreferences
« il: 17 Ottobre 2011, 23:03:11 CEST »
0
ciao a tutti, sto lavorando ad un app e nelle impostazioni vorrei usare un dialog con una seekbar.. ho trovato questo su internet
Codice (Java): [Seleziona]
// [url=http://www.java2s.com/Code/Android/UI/extendsDialogPreference.htm] extends DialogPreference : Dialog « UI « Android [/url]

import android.content.Context;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;

public class BarPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener {
  private static final String androidns = "http://schemas.android.com/apk/res/android";

  private SeekBar mBar;
  private TextView mMessageText, mValueText;

  private String mPostfix;
  private int mDefault = 0;
  private int mMax = 100;
  private int mValue = 0;

  public BarPreference(Context context, AttributeSet attrs) {
    super(context, attrs);
    //mPostfix = attrs.getAttributeValue(androidns, "postfix");
    mPostfix = attrs.getAttributeValue(androidns, "text");
    mDefault = attrs.getAttributeIntValue(androidns, "defaultValue", 0);
    mMax = attrs.getAttributeIntValue(androidns, "max", 100);
  }

  public void onProgressChanged(SeekBar seek, int value, boolean fromTouch) {
    String valueText = String.valueOf(value);
    mValueText.setText(mPostfix == null ? valueText : valueText + mPostfix);
    if (shouldPersist()){
      persistInt(value);
    }
    callChangeListener(new Integer(value));
  }

  public void onStartTrackingTouch(SeekBar seek) {
  }

  public void onStopTrackingTouch(SeekBar seek) {
  }
 
  protected View onCreateDialogView() {
    LinearLayout container = new LinearLayout(getContext());
    container.setOrientation(LinearLayout.VERTICAL);
    container.setPadding(10, 5, 10, 5);
   
   
    mMessageText = new TextView(getContext());
    mMessageText.setText(getSummary());
    container.addView(mMessageText);

    mValueText = new TextView(getContext());
    mValueText.setGravity(Gravity.CENTER_HORIZONTAL);
    container.addView(mValueText, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));

    mBar = new SeekBar(getContext());
    mBar.setOnSeekBarChangeListener(this);
    mBar.setPadding(5, 0, 5, 0);
    container.addView(mBar, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
   

    if (shouldPersist()){
      mValue = getPersistedInt(mDefault);
    }

    mBar.setMax(mMax);
    mBar.setProgress(mValue);
    return container;
  }

  protected void onBindDialogView(View v) {
    super.onBindDialogView(v);
    mBar.setMax(mMax);
    mBar.setProgress(mValue);
  }

  protected void onSetInitialValue(boolean restore, Object defaultValue) {
    super.onSetInitialValue(restore, defaultValue);
    if (restore)
      mValue = shouldPersist() ? getPersistedInt(mDefault) : 0;
    else
      mValue = (Integer) defaultValue;
  }    
}

questa Preference funziona ma ha un problema, non serve fare ok per salvare il valore, si salva appena la SeekBar viene spostata, questo fa si che Annulla non funzioni.. così ho provato a modificarla :
Codice (Java): [Seleziona]
public class MySeekBarPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener {
  private static final String androidns = "http://schemas.android.com/apk/res/android";

  private SeekBar mBar;
  private TextView mMessageText, mValueText;

  private String mPostfix;
  private int mDefault = 0;
  private int mMax = 100;
  private int mValue = 0;

  public MySeekBarPreference(Context context, AttributeSet attrs) {
    super(context, attrs);
    //mPostfix = attrs.getAttributeValue(androidns, "postfix");
    mPostfix = attrs.getAttributeValue(androidns, "text");
    mDefault = attrs.getAttributeIntValue(androidns, "defaultValue", 0);
    mMax = attrs.getAttributeIntValue(androidns, "max", 100);
  }

  public void onStartTrackingTouch(SeekBar seek) {
  }

  public void onStopTrackingTouch(SeekBar seek) {
  }
 
  protected View onCreateDialogView() {
         
    LinearLayout container = new LinearLayout(getContext());
    container.setOrientation(LinearLayout.VERTICAL);
    //container.setPadding(10, 5, 10, 5);
    container.setPadding(10, 5, 10, 5);
   
   
    mMessageText = new TextView(getContext());
    mMessageText.setText(getSummary());
    container.addView(mMessageText);

    mValueText = new TextView(getContext());
    mValueText.setGravity(Gravity.CENTER_HORIZONTAL);
    container.addView(mValueText, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));

    mBar = new SeekBar(getContext());
    mBar.setOnSeekBarChangeListener(this);
    mBar.setPadding(15, 0, 15, 0);
    container.addView(mBar, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
   

   if (shouldPersist()){
      mValue = getPersistedInt(mDefault);
   }

    mBar.setMax(mMax);
    mBar.setProgress(mValue);
    return container;
  }
 
  public void onProgressChanged(SeekBar seek, int value, boolean fromTouch) {
            String valueText = String.valueOf(value);
            mValueText.setText(mPostfix == null ? valueText : valueText + " " +mPostfix + "\n");
           
            mValue = value;
            /*
            if (shouldPersist()){
              persistInt(value);
            }
            callChangeListener(new Integer(value));
            */

  }
 
  @Override
  protected void onDialogClosed(boolean positiveResult) {
      super.onDialogClosed(positiveResult);

      if (positiveResult) {
         
          int newValue = mValue;
          persistInt(newValue);
          callChangeListener(newValue);
         
      }
     
  }

  protected void onBindDialogView(View v) {
    super.onBindDialogView(v);
    mBar.setMax(mMax);
    mBar.setProgress(mValue);
  }

  protected void onSetInitialValue(boolean restore, Object defaultValue) {
    super.onSetInitialValue(restore, defaultValue);
    if (restore)
      mValue = shouldPersist() ? getPersistedInt(mDefault) : 0;
    else
      mValue = (Integer) defaultValue;
  }    
}
/*
come dichiararla nel file xml
<MySeekBarPreference
        android:key="mySeekBar"
        android:title="Title"
        android:summary="Summary"
        android:text="postFix"
        android:defaultValue="1"
        android:max="10"      
        />

*/

su emulatore, sia con il 2.1 che il 2.3 funziona perfettamente, ma sul mio telefono no !! e dubito sia un problema del telefono..
precisamente, la preference salva il valore corretto ma quando il dialog si apre la seekbar non ha nè l'ultimo valore salvato, nè il default alla prima apertura, ha sempre 0

non avendo neanche mai fatto un dialog custom mi trovo spiazzato, in più non capisco perchè vada su emulatore e sul mio cellulare invece no..

allego un progetto con una activity che mostra il valore delle preference e una preference activity per provare BarPreference e MySeekBarPreference, ho fatto direttamente un file .zip della cartella presente nel Workspace..

EDIT : io ho provato, per sistemare ok e annulla, a far si che si salvasse solo premendo OK, ovviamente si potrebbe lasciare il salvataggio del valore nell'onProgressChanged e alla pressione di annulla ripristinare il valore precedentemente salvato..

Grazie in anticipo a chiunque mi darà una mano  ;-)
« Ultima modifica: 18 Ottobre 2011, 12:30:34 CEST da funcool »

Offline funcool

  • Nuovo arrivato
  • *
  • Post: 42
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Acer Liquid CM 7.1
  • Play Store ID:
    elcasa
  • Sistema operativo:
    Windows 8
Re:Custom Preference - Dialog con SeekBar & SharedPreferences
« Risposta #1 il: 18 Ottobre 2011, 21:47:49 CEST »
+1
oggi ci ho dato un'altra occhiata e ho risolto cosi, ve lo posto, magari può interessare:

Codice (Java): [Seleziona]
public class SeekBarAnnulla extends DialogPreference implements SeekBar.OnSeekBarChangeListener {
        private static final String androidns = "http://schemas.android.com/apk/res/android";

        private SeekBar mBar;
        private TextView mMessageText, mValueText;

        private String mPostfix;
        private int mDefault = 0;
        private int mMax = 100;
        private int mValue = 0;
       
        private int oldValue;
       
        public SeekBarAnnulla(Context context, AttributeSet attrs) {
                super(context, attrs);
                //mPostfix = attrs.getAttributeValue(androidns, "postfix");
                mPostfix = attrs.getAttributeValue(androidns, "text");
                mDefault = attrs.getAttributeIntValue(androidns, "defaultValue", 0);
                mMax = attrs.getAttributeIntValue(androidns, "max", 100);
        }

        public void onProgressChanged(SeekBar seek, int value, boolean fromTouch) {
                String valueText = String.valueOf(value);
       
                mValueText.setText(mPostfix == null ? valueText : valueText + mPostfix);
               
                if (shouldPersist()){
                        persistInt(value);
                }
                callChangeListener(new Integer(value));
        }

        public void onStartTrackingTouch(SeekBar seek) {
        }

        public void onStopTrackingTouch(SeekBar seek) {
        }
       
        protected void onSetInitialValue(boolean restore, Object defaultValue) {
                super.onSetInitialValue(restore, defaultValue);
                if (restore)
                        mValue = shouldPersist() ? getPersistedInt(mDefault) : 0;
                else
                        mValue = (Integer) defaultValue;
                               
        }

        protected View onCreateDialogView() {
                LinearLayout container = new LinearLayout(getContext());
                container.setOrientation(LinearLayout.VERTICAL);
                container.setPadding(10, 5, 10, 5);
 
 
                mMessageText = new TextView(getContext());
                mMessageText.setText(getSummary());
                container.addView(mMessageText);

                mValueText = new TextView(getContext());
                mValueText.setGravity(Gravity.CENTER_HORIZONTAL);
                container.addView(mValueText, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));

                mBar = new SeekBar(getContext());
                mBar.setOnSeekBarChangeListener(this);
                //mBar.setPadding(5, 0, 5, 0);
            mBar.setPadding(15, 0, 15, 0);
                container.addView(mBar, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
 

                if (shouldPersist()){
                        mValue = getPersistedInt(mDefault);
                }

                mBar.setMax(mMax);
                mBar.setProgress(mValue);
               
                oldValue = mValue; // SALVO IL VALORE DI APERTURA DEL DIALOG
                return container;
        }

        protected void onBindDialogView(View v) {
                super.onBindDialogView(v);
                mBar.setMax(mMax);
                mBar.setProgress(mValue);
        }

       
       
        @Override
        protected void onDialogClosed(boolean positiveResult) {
            super.onDialogClosed(positiveResult);
               
           
            if (!positiveResult) { // CASO ANNULLA E BACK
                               
                discard();
                                 
              }
               
           
          }
               
        private void discard(){
               
                if (shouldPersist()){
                persistInt(oldValue);
                }
                callChangeListener(new Integer(oldValue));
        }
       
       
}

in pratica ho lasciato che il valore si salvasse nell'onProgressChanged(), in caso di pressione annulla o back chiamo la discard() che mi salva il vecchio valore