2012-04-12 7 views
15

Sebbene sia in corso la documentazione, utilizzando "%s", è possibile visualizzare il valore selezionato come sommario, non funziona come previsto.Il testo di riepilogo ListPreference non viene aggiornato automaticamente ogni volta che si modifica la selezione

http://developer.android.com/reference/android/preference/ListPreference.html#getSummary%28%29

sto avendo il seguente preferences.xml

<?xml version="1.0" encoding="utf-8"?> 
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 
    <PreferenceCategory 
     android:title="@string/preference_xxx_category"> 
     <CheckBoxPreference 
      android:title="@string/preference_xxx_mode_title" 
      android:defaultValue="false" 
      android:summary="@string/preference_xxx_mode_summary" 
      android:key="xxxModePreference" /> 
    </PreferenceCategory> 

    <PreferenceCategory 
     android:title="@string/preference_yyy_category"> 
     <ListPreference 
      android:title="@string/preference_yyy_mode_title" 
      android:defaultValue="0" 
      android:entries="@array/yyy" 
      android:entryValues="@array/yyy_values" 
      android:summary="%s" 
      android:key="yyyModePreference" />   
    </PreferenceCategory> 

</PreferenceScreen> 

ed ecco la mia arrays.xml

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <string-array name="yyy"> 
     <item>Display value 0</item> 
     <item>Display value 1</item> 
    </string-array> 

    <string-array name="yyy_values"> 
     <item>0</item> 
     <item>1</item> 
    </string-array>  
</resources> 

Quello che mi aspettavo di avere il seguente codice Java per costruire una completa attività di preferenza, con una casella di controllo e una preferenza di lista, il testo di riepilogo della preferenza di lista può essere aggiornato automaticamente, quando mai eseguo la selezione. Il testo di riepilogo si alternerà tra Valore visualizzato 0 e Valore visualizzato 1.

public class Preferences extends PreferenceActivity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     addPreferencesFromResource(R.xml.preferences); 
    } 
} 

Tuttavia, mi rendo conto che il testo di riepilogo per la preferenza dell'elenco non si aggiornerà automaticamente. Solo quando eseguo il segno di spunta/deseleziona sulla casella di controllo, solo l'intera attività sarà invalidata e il testo di riepilogo per la preferenza dell'elenco verrà aggiornato SOLO.

Quindi, devo rivedere il mio codice come segue, che sembra più ingombrante.

public class Preferences extends PreferenceActivity implements OnSharedPreferenceChangeListener { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     addPreferencesFromResource(R.xml.preferences); 
     PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 

     // Cumbersome way to make sure list preference's summary text is being updated. 
     final String key = "yyyModePreference"; 
     ListPreference listPreference = (ListPreference)findPreference(key); 
     final String value = PreferenceManager.getDefaultSharedPreferences(this).getString(key, key); 
     final int index = listPreference.findIndexOfValue(value); 
     if (index >= 0) { 
      final String summary = (String)listPreference.getEntries()[index];   
      listPreference.setSummary(summary); 
     } 
    } 

    @Override 
    public void onSharedPreferenceChanged(SharedPreferences options, String key) { 
     // Cumbersome way to make sure list preference's summary text is being updated. 
     if (key.equals("yyyModePreference")) { 
      ListPreference listPreference = (ListPreference)findPreference(key); 
      final String value = options.getString(key, key); 
      final int index = listPreference.findIndexOfValue(value);    
      if (index >= 0) { 
       final String summary = (String)listPreference.getEntries()[index];   
       listPreference.setSummary(summary); 
      } 
     } 
    } 
} 

È un modo corretto? Esiste un modo semplificato per garantire che il testo di riepilogo di ListPreference venga sempre aggiornato automaticamente ogni volta che si verifica un cambiamento nella selezione.

+0

Grazie, mi ci sarebbe voluto molto tempo per capirlo. – Gerhard

+0

possibile duplicato di [Modifica il riepilogo di un ListPreference con il nuovo valore (Android)] (http://stackoverflow.com/questions/7017082/change-the-summary-of-a-listpreference-with-the-new- value-android) – CAMOBAP

risposta

24

Questo è un problema che esisteva su piattaforme prima KITKAT (cioè android-4.4_r0.7), ed è fissato da impegnare 94c02a1

La soluzione da opere @ilomambo, ma non può essere il migliore . Ho letto la fonte di ListPreference e ho trovato questa soluzione:

File: ListPreferenceCompat.java

package com.example.yourapplication; 

import android.content.Context; 
import android.os.Build; 
import android.preference.ListPreference; 
import android.text.TextUtils; 
import android.util.AttributeSet; 

public class ListPreferenceCompat extends ListPreference { 

    @TargetApi(Build.VERSION_CODES.LOLLIPOP) 
    public ListPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 
     super(context, attrs, defStyleAttr, defStyleRes); 
    } 

    @TargetApi(Build.VERSION_CODES.LOLLIPOP) 
    public ListPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    public ListPreferenceCompat(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public ListPreferenceCompat(Context context) { 
     super(context); 
    } 

    // NOTE: 
    // The framework forgot to call notifyChanged() in setValue() on previous versions of android. 
    // This bug has been fixed in android-4.4_r0.7. 
    // Commit: platform/frameworks/base/+/94c02a1a1a6d7e6900e5a459e9cc699b9510e5a2 
    // Time: Tue Jul 23 14:43:37 2013 -0700 
    // 
    // However on previous versions, we have to workaround it by ourselves. 
    @Override 
    public void setValue(String value) { 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 
      super.setValue(value); 
     } else { 
      String oldValue = getValue(); 
      super.setValue(value); 
      if (!TextUtils.equals(value, oldValue)) { 
       notifyChanged(); 
      } 
     } 
    } 
} 

Quando è necessario utilizzare ListPreference in XML, è sufficiente sostituire il tag com.example.yourapplication.ListPreferenceCompat.

Funziona perfettamente sul mio dispositivo Samsung S4 con Android 4.3 e all'interno di una delle mie app di produzione.

+0

Grazie per questo, funziona perfettamente! –

+0

Grazie, mi hai salvato un sacco di cose noiose !! –

6

immagino la sua una sorta di uno strano bug, perché l'ho provato su emulatore in esecuzione Android 2.3.3 e non ha funzionato, ma quando l'ho testato su 4.0.3 ha funzionato. Quello che ho fatto è stato android:summary="%s" in xml per ListPreference e questo è tutto.

+1

non è un bug. è una funzionalità che è stata aggiunta in api livello 15 (o forse 14). – Ran

+0

grazie a @Waqas per averlo indicato, una settimana fa ho cercato su Google una risposta molto più complessa in cui un listener doveva essere collegato e il riepilogo accede a livello di programmazione per fare la stessa cosa. – sonjz

1

IMHO è un bug. L'onClickListener() definita in ListPreference.java#builder.setSingleChoiceItems() non chiama notifyChanged()

mi capita di essere di codifica mia ListPreference sulla base di quel codice, e attraversò di corsa lo stesso problema come il PO, ho aggiunto notifyChanged():

  ... 
      dialog.dismiss(); 
      notifyChanged(); // <<<<<<<<<< 
     } 
}); 

e ora il sommario delle preferenze viene aggiornato non appena lo scelgo. Non dipende dalla versione di Android, ListPreference è stato codificato in questo modo da sempre.

Problemi correlati