2012-04-12 14 views
15

Mimo że dokumentacja jest udokumentowana, przy użyciu "%s" mogę wyświetlić wybraną wartość jako podsumowanie, ale nie działa zgodnie z oczekiwaniami.Tekst podsumowania listyPreferencji nie jest automatycznie aktualizowany, gdy nastąpi zmiana w wyborze

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

Mam następujący 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> 

i tu jest moje 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> 

Czego spodziewa się poprzez następujący kod Java do tworzenia kompletnej aktywności preferencji, z polem wyboru i preferencją listy, tekst podsumowania preferencji listy może być aktualizowany automatycznie, kiedy kiedykolwiek dokonuję selekcji. Tekst podsumowania będzie przełączał się pomiędzy Wartość wyświetlana 0 i Wartość wyświetlana 1.

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

Jednak zdaję sobie sprawę, że tekst podsumowania preferencji listy nie zaktualizuje się automatycznie. Tylko wtedy, gdy zaznaczę pole wyboru "zaznacz/odznacz", tylko cała aktywność zostanie unieważniona, a tekst podsumowania preferencji listy będzie TYLKO aktualizowany.

W związku z tym muszę poprawić mój kod w następujący sposób, który wygląda bardziej niewygodne.

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); 
      } 
     } 
    } 
} 

Czy to jest poprawny sposób? Czy istnieje jakiś uproszczony sposób, aby zapewnić, że tekst podsumowania ListPreference będzie zawsze aktualizowany automatycznie, gdy nastąpi zmiana w wyborze.

+0

Dziękuję, zajęłoby mi to dużo czasu, aby to zrozumieć. – Gerhard

+0

możliwy duplikat [Zmień podsumowanie ListPreference z nową wartością (Android)] (http://stackoverflow.com/questions/7017082/change-the-summary-of-a-listpreference-with-the-new- value-android) – CAMOBAP

Odpowiedz

24

Jest to błąd, który istniał na platformach przed KitKat (tj android-4.4_r0.7) i jest ona ustalana przez popełnić 94c02a1

roztworu z prac @ilomambo, ale nie może być najlepszy . Przeczytałem źródło ListPreference i wpadłem na to rozwiązanie:

Plik: 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(); 
      } 
     } 
    } 
} 

Kiedy trzeba użyć ListPreference w xml, wystarczy zastąpić tag com.example.yourapplication.ListPreferenceCompat.

To działa zgrabnie na moim urządzeniu Samsung S4 z Androidem 4.3 i wewnątrz jednej z aplikacji produkcyjnych.

+0

Dzięki temu działa idealnie! –

+0

Dzięki, oszczędzasz mi wiele nudnych rzeczy !! –

6

Chyba jej jakiś dziwny błąd, ponieważ Przetestowałem go na emulatorze z systemem Android 2.3.3i to nie działa, ale gdy testowałem go na 4.0.3 to działało. To co zrobiłem to android:summary="%s" w xml dla ListPreference i to wszystko.

+1

to nie jest błąd. to funkcja dodana na poziomie 15 api (a może 14). – Ran

+0

dziękuje @Waqas za wskazanie tego, tydzień temu i googled o wiele bardziej zaangażowaną odpowiedź, gdzie musiał być dołączony słuchacz i podsumowanie dostęp programowo, aby zrobić to samo. – sonjz

1

IMHO to błąd. OnClickListener() zdefiniowana w ListPreference.java#builder.setSingleChoiceItems() nie nazywają notifyChanged()

zdarza mi się być kodowanie własną ListPreference na podstawie tego kodeksu, i biegł ten sam problem jak PO, dodałem notifyChanged():

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

i teraz podsumowanie preferencji jest aktualizowane, gdy tylko go wybiorę. Nie jest zależna od wersji Androida, ListPreference została tak zakodowana od zawsze.

Powiązane problemy