Wie zeige ich den aktuellen Wert einer Android-Voreinstellung in der Voreinstellungszusammenfassung an?

457

Dies muss sehr oft vorkommen.

Wenn der Benutzer Einstellungen in einer Android-App bearbeitet, möchte er, dass er den aktuell festgelegten Wert der Einstellungen in der PreferenceZusammenfassung sehen kann.

Beispiel: Wenn ich eine Voreinstellung für "Alte Nachrichten verwerfen" habe, die die Anzahl der Tage angibt, nach denen Nachrichten bereinigt werden müssen. In der PreferenceActivitymöchte ich den Benutzer sehen:

"Alte Nachrichten verwerfen" <- Titel

"Nachrichten nach x Tagen bereinigen " <- Zusammenfassung, wobei x der aktuelle Voreinstellungswert ist

Zusätzliches Guthaben: Machen Sie dies wiederverwendbar, damit ich es unabhängig von ihrem Typ problemlos auf alle meine Einstellungen anwenden kann (damit es mit EditTextPreference, ListPreference usw. mit minimalem Codierungsaufwand funktioniert).

nyenyec
quelle

Antworten:

151

Es gibt Möglichkeiten, dies zu einer allgemeineren Lösung zu machen, wenn dies Ihren Anforderungen entspricht.

Wenn Sie beispielsweise generell möchten, dass alle Listeneinstellungen ihre Auswahl als Zusammenfassung anzeigen, können Sie dies für Ihre onSharedPreferenceChangedImplementierung verwenden:

public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    Preference pref = findPreference(key);

    if (pref instanceof ListPreference) {
        ListPreference listPref = (ListPreference) pref;
        pref.setSummary(listPref.getEntry());
    }
}

Dies ist leicht auf andere Präferenzklassen erweiterbar.

Wenn Sie die getPreferenceCountund getPreference-Funktionalität in PreferenceScreenund verwenden PreferenceCategory, können Sie leicht eine generische Funktion schreiben, um durch den Präferenzbaum zu gehen und die Zusammenfassungen aller Präferenzen der gewünschten Typen auf ihre toStringDarstellung festzulegen

Dutzend Krähen
quelle
6
schöne Lösung in der Tat. fehlt nur eine Initialisierung
njzk2
9
@ njzk2 alles was Sie tun müssen, ist sicherzustellen, dass die Aktivitätimplements OnSharedPreferenceChangeListener
4
NB: Es gibt einen einfacheren Weg, siehe @ Robertas 'Antwort .
Salman von Abbas
6
Tatsächlich können Sie die Zusammenfassung auf "%s"für einstellen ListPreferenceund ListPreference.getSummary()die Zusammenfassung mit dem aktuell ausgewählten Eintrag formatieren (oder ""falls keiner ausgewählt ist).
SOFe
findPreference (Schlüssel) ist veraltet. Gibt es eine andere Möglichkeit, darauf zuzugreifen?
Nie mehr
144

Hier ist meine Lösung ... FWIW

package com.example.PrefTest;

import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceManager;

public class Preferences extends PreferenceActivity implements
        OnSharedPreferenceChangeListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
        PreferenceManager.setDefaultValues(Preferences.this, R.xml.preferences,
            false);
        initSummary(getPreferenceScreen());
    }

    @Override
    protected void onResume() {
        super.onResume();
        // Set up a listener whenever a key changes
        getPreferenceScreen().getSharedPreferences()
                .registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // Unregister the listener whenever a key changes
        getPreferenceScreen().getSharedPreferences()
                .unregisterOnSharedPreferenceChangeListener(this);
    }

    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
            String key) {
        updatePrefSummary(findPreference(key));
    }

    private void initSummary(Preference p) {
        if (p instanceof PreferenceGroup) {
            PreferenceGroup pGrp = (PreferenceGroup) p;
            for (int i = 0; i < pGrp.getPreferenceCount(); i++) {
                initSummary(pGrp.getPreference(i));
            }
        } else {
            updatePrefSummary(p);
        }
    }

    private void updatePrefSummary(Preference p) {
        if (p instanceof ListPreference) {
            ListPreference listPref = (ListPreference) p;
            p.setSummary(listPref.getEntry());
        }
        if (p instanceof EditTextPreference) {
            EditTextPreference editTextPref = (EditTextPreference) p;
            if (p.getTitle().toString().toLowerCase().contains("password"))
            {
                p.setSummary("******");
            } else {
                p.setSummary(editTextPref.getText());
            }
        }
        if (p instanceof MultiSelectListPreference) {
            EditTextPreference editTextPref = (EditTextPreference) p;
            p.setSummary(editTextPref.getText());
        }
    }
}
EddieB
quelle
Dies funktioniert hervorragend @EddieB ... außer dass ich einen Einstellungsbildschirm innerhalb eines Einstellungsbildschirms habe. Haben Sie eine Idee, wie Sie den inneren Einstellungsbildschirm erreichen und diese mit einer Zusammenfassung füllen können?
Taraloca
@taraloca - change if (p Instanz von PreferenceCategory) {PreferenceCategory pCat = (PreferenceCategory) p; to if (p Instanz von PreferenceGroup) {final PreferenceGroup pCat = (PreferenceGroup) p;
Martin Ždila
dies funktioniert großartig was ist, wenn EditTextPreferenceist android:password="true" es , den Wert zeigt
Chathura Wijesinghe
1
Wie soll ich den Code ändern, um eine Zusammenfassung aus der Ressourcendatei (XML) anzuzeigen, wenn kein Wert definiert ist (dh if editTextPref.getText() == "")? Wie erhalte ich einen zusammenfassenden Wert bei updatePrefSummary? p.getSummary()und editTextPref.getSummary()geben Sie bereits geänderte Werte zurück.
LA_
Da beide PreferenceCategoryund von PreferenceScreenerben PreferenceGroup, habe ich geändert initSummary, um PreferenceGroupstattdessen ein zu behandeln . Dies vermeidet die Notwendigkeit einer weiteren Schleife onCreate(). Verhaltensänderung: Verschachtelte PreferenceScreens werden jetzt auch rekursiv behandelt.
Lekensteyn
96

Laut Android- Dokumentation kann ein String-Formatierungsmarker verwendet werden in getSummary():

Wenn die Zusammenfassung einen String-Formatierungsmarker enthält (dh "% s" oder "% 1 $ s"), wird der aktuelle Eintragswert an seiner Stelle ersetzt.

Das android:summary="Clean up messages after %s days"einfache Angeben in der ListPreference-XML-Deklaration hat bei mir funktioniert.

Hinweis: Dies funktioniert nur für ListPreference.

Robertas
quelle
Jemand korrigiert mich, wenn ich falsch liege, aber die Dokumentation für getSummary () besagt, dass es in API-Ebene 1 hinzugefügt wurde. Bedeuten Sie, dass das Verhalten bei der ersten Veröffentlichung anders war?
TheIT
10
Leider funktioniert dies nur für ListPreference. Ich möchte das gleiche Verhalten für EditTextPreference. Es ist überraschend, dass Google dies nicht für alle DialogPreferences hinzugefügt hat.
Vicki
2
Außerdem arbeite ich nicht, solange der Wert nicht festgelegt wurde. Beim ersten Aufruf der Voreinstellungsaktivität werden nur% s angezeigt, was wirklich dumm ist.
Zordid
3
@Zordid Dies kann behoben werden, indem der Standardwert in Ihrer XML wie android:defaultValue="0"in Ihrer ListPreference angegeben wird. Dies ist die vernünftigste Antwort und funktioniert für mich.
Mohit Singh
@Mohit Singh / @Zordid, auf Lollipop API 22 funktionieren die defaultValueund die %snicht. Bei anderen Versionen funktioniert es jedoch im Allgemeinen. Irgendeine Lösung bitte? Ich möchte sicher keine benutzerdefinierte Klasse dafür schreiben. Unglaublich, dass Google die trivialsten Aufgaben so schmerzhaft macht.
Narayana J
81

Wenn Sie verwenden PreferenceFragment, habe ich es so gelöst. Es ist selbsterklärend.

public static class SettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      addPreferencesFromResource(R.xml.settings);
      getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onResume() {
      super.onResume();
      for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); ++i) {
        Preference preference = getPreferenceScreen().getPreference(i);
        if (preference instanceof PreferenceGroup) {
          PreferenceGroup preferenceGroup = (PreferenceGroup) preference;
          for (int j = 0; j < preferenceGroup.getPreferenceCount(); ++j) {
            Preference singlePref = preferenceGroup.getPreference(j);
            updatePreference(singlePref, singlePref.getKey());
          }
        } else {
          updatePreference(preference, preference.getKey());
        }
      }
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
      updatePreference(findPreference(key), key);
    }

    private void updatePreference(Preference preference, String key) {
      if (preference == null) return;
      if (preference instanceof ListPreference) {
        ListPreference listPreference = (ListPreference) preference;
        listPreference.setSummary(listPreference.getEntry());
        return;
      }
      SharedPreferences sharedPrefs = getPreferenceManager().getSharedPreferences();
      preference.setSummary(sharedPrefs.getString(key, "Default"));
    }
  }
tdevaux
quelle
3
Diese Lösung benötigt mehr Stimmen ... Es nervt mich, dass die Beispiele auf der Entwicklerseite zeigen, dass dies getan wird, aber es vollständig weglassen.
Justin Smith
3
Um EditTextPreferences ebenfalls zu aktualisieren, fügen Sie dies zu updatePreferenceCODE hinzu. if (preference instanceof EditTextPreference) { EditTextPreference editTextPref = (EditTextPreference) preference; preference.setSummary(editTextPref.getText()); }Danke @EddieB
Eugene van der Merwe
6
Wo rufst du an unregisterOnSharedPreferenceChangeListener?
CAMOBAP
1
findPreference(CharSequence key) This method was deprecated in API level 11. This function is not relevant for a modern fragment-based PreferenceActivity.
DSlomer64
2
@ DSlomer64 Mir ist klar, was Sie zitieren. Es fordert Sie auf, nicht PreferenceActivity.findPreference(und mehrere andere Methoden) zu verwenden, da Google möchte, dass Sie zu der in dieser Antwort gezeigten Technik wechseln, die PreferenceFragment.findPreferencestattdessen verwendet wird.
Dan Hulme
33

Meine Option ist, ListPreference zu erweitern und es ist sauber:

public class ListPreferenceShowSummary extends ListPreference {

    private final static String TAG = ListPreferenceShowSummary.class.getName();

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

    public ListPreferenceShowSummary(Context context) {
        super(context);
        init();
    }

    private void init() {

        setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

            @Override
            public boolean onPreferenceChange(Preference arg0, Object arg1) {
                arg0.setSummary(getEntry());
                return true;
            }
        });
    }

    @Override
    public CharSequence getSummary() {
        return super.getEntry();
    }
}

Dann fügen Sie in Ihrer settings.xml hinzu:

<yourpackage.ListPreferenceShowSummary
    android:key="key" android:title="title"
    android:entries="@array/entries" android:entryValues="@array/values"
    android:defaultValue="first value"/>
Youyougoslave
quelle
Darauf aufbauend habe ich eine Lösung gefunden. In meiner Lösung habe ich eine Methode, um ein Array von entrySummaries festzulegen, anstatt die Eintragszeichenfolgen sowohl im Menü als auch in den Zusammenfassungen zu verwenden. Hier gibt es ein Problem: getEntry () gibt den vorherigen Wert zurück, nicht den neuen.
Pzulw
1
Ist init () überhaupt notwendig? Ich habe gerade getSummary () überschrieben und es scheint perfekt zu funktionieren!
Andy
4
Scheint eine viel einfachere und sauberere Lösung zu sein als die am höchsten gewählte!
muslidrikk
2
Die init()Funktion ist erforderlich, um zu aktualisieren, summarywann der Benutzer diese Einstellung ändert. Ohne es bleibt es einfach, was auch immer der Eintrag ursprünglich war.
Anthonylawson
23

Sie können Standardeinstellungsklassen überschreiben und die Funktion implementieren.

public class MyListPreference extends ListPreference  {
    public MyListPreference(Context context) { super(context); }
    public MyListPreference(Context context, AttributeSet attrs) { super(context, attrs); }
    @Override
    public void setValue(String value) {
        super.setValue(value);
        setSummary(getEntry());
    }
}

Später in Ihrer XML können Sie benutzerdefinierte Einstellungen wie verwenden

<your.package.name.MyListPreference 
    android:key="noteInterval"
    android:defaultValue="60"
    android:title="Notification Interval"
    android:entries="@array/noteInterval"
    android:entryValues="@array/noteIntervalValues"
    />
Palani
quelle
Hervorragende einfache Methode. Achten Sie einfach auf Dinge wie% in der getEntry-Zeichenfolge, da diese Probleme verursachen könnten (oder für mich)
Andrew
21

Nach einigen Stunden, die ich damit verbracht habe, ein solches Problem zu lösen, habe ich diesen Code implementiert:

[UPDATE: die endgültige Versionsliste]

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

        m_updateList = (ListPreference) findPreference(getString(R.string.pref_update_interval_key));
        String currentValue = m_updateList.getValue();
        if (currentValue == null) {
            m_updateList.setValue((String)m_updateList.getEntryValues()[DEFAULT_UPDATE_TIME_INDEX]);
            currentValue = m_updateList.getValue();
        }
        updateListSummary(currentValue);    

        m_updateList.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                updateListSummary(newValue.toString());
                return true;
            }       
        });     
    }

    private void updateListSummary(String newValue) {
        int index = m_updateList.findIndexOfValue(newValue);
        CharSequence entry = m_updateList.getEntries()[index];
        m_updateList.setSummary(entry);
    }
}

Das war die einzige Lösung, die für mich gut funktioniert hat. Bevor ich versucht habe, eine Unterklasse von ListPreferences zu erstellen und Android zu implementieren: summary = "bla bla bla% s". Beides hat nicht funktioniert.

Subtiler Fuchs
quelle
Ihr Weg ist klarer und verwendet weniger Code als andere. Die Top-Antworten funktionieren mit "Proxy" - Einstellungsmanager. Es ist nicht so klar, wie auf direkte Änderungen in der Liste zu achten.
Paul Annekov
@Subtle Fox, ordentliche Lösung. Nur neugierig, ob Sie 'setDefaultValue ()' gemacht haben, warum dann nach (ss == null) suchen
Samuel
Weil setDefaultValue () nicht da sein sollte :) Ich habe diesen Code vor dem Refactoring eingefügt
Subtle Fox
20

Vielleicht wie ListPreference: Ändern Sie getSummary, um das zu erhalten, was Sie wollen:

package your.package.preference;

import android.content.Context;
import android.util.AttributeSet;

public class EditTextPreference extends android.preference.EditTextPreference{
        public EditTextPreference(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }

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

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

        @Override
        public CharSequence getSummary() {
            if(super.getSummary() == null) return null;

            String summary = super.getSummary().toString();
            return String.format(summary, getText());
        }
    }

Und verwenden Sie dies in Ihrer XML:

<your.package.EditTextPreference
                android:key="pref_alpha"
                android:summary="Actual value: %s"
                android:title="Title"
                android:defaultValue="default"
                />

Sie können also %sanstelle des tatsächlichen Werts eine Zusammenfassung mit schreiben .

Eruvanos
quelle
1
@Eruvanos @ serv-inc Zumindest mit einer Unterklasse von android.support.v7.preference.EditTextPreferencewird die Zusammenfassung nicht aktualisiert, wenn die Voreinstellung geändert wird, sondern nur, wenn die Voreinstellungsaktivität erstellt wird. Ein Weg, dies zu OnSharedPreferenceChangeListener.onSharedPreferenceChangedandroid.support.v7.preference.EditTextPreference.setText(String text)@Override public void setText(String text) { super.setText(text); this.setSummary(this.getText()); }
umgehen,
@PointedEars: fertig. Dies scheint aber auch eine Kopie von stackoverflow.com/a/21906829/1587329
serv-inc
18

Dies ist der Code, den Sie benötigen, um die Zusammenfassung auf den ausgewählten Wert zu setzen. Außerdem werden die Werte beim Start festgelegt und die Standardwerte werden nicht nur beim Ändern berücksichtigt. Ändern Sie einfach "R.layout.prefs" in Ihre XML-Datei und erweitern Sie die setSummary-Methode nach Ihren Wünschen. Es werden eigentlich nur ListPreferences behandelt, aber es ist einfach anzupassen, um andere Einstellungen zu berücksichtigen.

package de.koem.timetunnel;

import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;

public class Prefs 
    extends PreferenceActivity 
    implements OnSharedPreferenceChangeListener {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

       this.addPreferencesFromResource(R.layout.prefs);
       this.initSummaries(this.getPreferenceScreen());

       this.getPreferenceScreen().getSharedPreferences()
           .registerOnSharedPreferenceChangeListener(this);
    }

  /**
    * Set the summaries of all preferences
    */
  private void initSummaries(PreferenceGroup pg) {
      for (int i = 0; i < pg.getPreferenceCount(); ++i) {
          Preference p = pg.getPreference(i);
          if (p instanceof PreferenceGroup)
              this.initSummaries((PreferenceGroup) p); // recursion
          else
              this.setSummary(p);
      }
  }

  /**
    * Set the summaries of the given preference
    */
  private void setSummary(Preference pref) {
      // react on type or key
      if (pref instanceof ListPreference) {
          ListPreference listPref = (ListPreference) pref;
          pref.setSummary(listPref.getEntry());
      }
  }

  /**
    * used to change the summary of a preference
    */
  public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
     Preference pref = findPreference(key);
     this.setSummary(pref);
  }

  // private static final String LOGTAG = "Prefs";
}

Koem

Koem
quelle
Vielen Dank! Daraus habe ich eine Klasse erstellt, in der die Ressourcen-ID als Argument für onCreate () angegeben wurde. Auf diese Weise wurde eine einzeilige Änderung an meinen Einstellungsbildschirmen vorgenommen, damit die Werte zusammengefasst angezeigt werden.
Asmo Soinio
2
Übrigens: Beachten Sie, dass nicht persistente Einstellungen mit diesem System nicht aktualisiert werden. Änderungen an ihnen müssen mit der setOnPreferenceChangeListener(Preference.OnPreferenceChangeListener onPreferenceChangeListener)Methode der einzelnen Einstellungen abgehört werden .
Asmo Soinio
11

Tatsächlich kann CheckBoxPreference basierend auf dem Kontrollkästchenwert eine andere Zusammenfassung angeben. Siehe die Attribute android: summaryOff und android: summaryOn (sowie die entsprechenden CheckBoxPreference-Methoden).

dhaag23
quelle
11

Für EditTextPreference:

public class MyEditTextPreference extends EditTextPreference {
    public MyEditTextPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

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

    @Override
    public void setText(String text) {
        super.setText(text);
        setSummary(text);
    }
}
Lordmegamax
quelle
9

Wenn jemand immer noch nach Antworten darauf sucht, sollten Sie die Antwort von dreiunddreißig lesen .

<ListPreference
    android:key="pref_list"
    android:title="A list of preferences"
    android:summary="%s"
    android:entries="@array/pref_list_entries"
    android:entryValues="@array/pref_list_entries_values"
    android:defaultValue="0" />

Android ersetzt% s durch den aktuellen Zeichenfolgenwert der Voreinstellung, wie er von der Auswahl der ListPreference angezeigt wird.

Irritator
quelle
Funktioniert. Dies ist heute die einfachste und beste Lösung.
Davidgyoung
1
Beachten Sie, dass "% s" an einer beliebigen Stelle in Ihrer Zusammenfassungszeichenfolge platziert werden kann. Und ja, das schließt Ressourcenzeichenfolgen ein!
Scott Biggs
7

Danke für diesen Tipp!

Ich habe einen Einstellungsbildschirm und möchte den Wert für jede Listeneinstellung als Zusammenfassung anzeigen.

Das ist jetzt mein Weg:

public class Preferences extends PreferenceActivity implements OnSharedPreferenceChangeListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
}

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

    // Set up initial values for all list preferences
    Map<String, ?> sharedPreferencesMap = getPreferenceScreen().getSharedPreferences().getAll();
    Preference pref;
    ListPreference listPref;
    for (Map.Entry<String, ?> entry : sharedPreferencesMap.entrySet()) {
        pref = findPreference(entry.getKey());
        if (pref instanceof ListPreference) {
            listPref = (ListPreference) pref;
            pref.setSummary(listPref.getEntry());
        }
    }

    // Set up a listener whenever a key changes            
    getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}

@Override
protected void onPause() {
    super.onPause();

    // Unregister the listener whenever a key changes            
    getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);    
}

public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    Preference pref = findPreference(key);

    if (pref instanceof ListPreference) {
        ListPreference listPref = (ListPreference) pref;
        pref.setSummary(listPref.getEntry());
    }
}

Das funktioniert bei mir, aber ich frage mich, was die beste Lösung ist (Leistung, Stabilität, Skalierbarkeit): die, die Koem zeigt, oder diese?

alexx
quelle
6

Danke, Reto, für die ausführliche Erklärung!

Für den Fall, dass dies jemandem hilft, musste ich den von Reto Meier vorgeschlagenen Code ändern, damit er mit dem SDK für Android 1.5 funktioniert

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

    // Setup the initial values
    mListPreference.setSummary("Current value is " + mListPreference.getEntry().toString()); 

    // Set up a listener whenever a key changes            
    ...
}

Die gleiche Änderung gilt für die Rückruffunktion onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)

Prost,

Chris

Chris
quelle
4

Ich habe das Problem mit dem folgenden Nachkommen von ListPreference gelöst:

public class EnumPreference extends ListPreference {

    public EnumPreference(Context aContext, AttributeSet attrs) {
        super(aContext,attrs);
    }

    @Override
    protected View onCreateView(ViewGroup parent) {
        setSummary(getEntry());
        return super.onCreateView(parent);
    }

    @Override
    protected boolean persistString(String aNewValue) {
        if (super.persistString(aNewValue)) {
            setSummary(getEntry());
            notifyChanged();
            return true;
        } else {
            return false;
        }
    }
}

Scheint für mich in 1.6 bis 4.0.4 gut zu funktionieren.

Onkel Code Affe
quelle
4
public class ProfileManagement extends PreferenceActivity implements
OnPreferenceChangeListener {
    EditTextPreference screenName;
    ListPreference sex;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.layout.profile_management);

            screenName = (EditTextPreference) findPreference("editTextPref");
            sex = (ListPreference) findPreference("sexSelector");

            screenName.setOnPreferenceChangeListener(this);
            sex.setOnPreferenceChangeListener(this);

    }   

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        preference.setSummary(newValue.toString());
        return true;
    }
}
GalkinAndrew
quelle
4

Ich habe gesehen, dass alle abgestimmten Antworten zeigen, wie die Zusammenfassung mit dem genauen aktuellen Wert eingestellt wird, aber das OP wollte auch so etwas wie:

"Nachrichten nach x Tagen bereinigen" * <- Zusammenfassung, wobei x der aktuelle Voreinstellungswert ist

Hier ist meine Antwort, um das zu erreichen

Wie die Dokumentation sagt über ListPreference.getSummary():

Gibt die Zusammenfassung dieser ListPreference zurück. Wenn die Zusammenfassung einen String-Formatierungsmarker enthält (dh "% s" oder "% 1 $ s"), wird der aktuelle Eintragswert an seiner Stelle ersetzt.

Ich habe es jedoch auf mehreren Geräten versucht und es scheint nicht zu funktionieren. Mit einigen Recherchen habe ich in dieser Antwort eine gute Lösung gefunden . Es besteht einfach darin, alles, was PreferenceSie verwenden und überschreiben, so getSummary()zu erweitern, dass es wie in der Android-Dokumentation angegeben funktioniert.

Christian García
quelle
1
Es scheint anfangs zu funktionieren, aber wenn Sie einen neuen Wert auswählen, wird es nicht automatisch aktualisiert, bis Sie etwas tun, um die gesamte Aktivität ungültig zu machen und sie neu zu zeichnen. Ich bin auf Android 4.0.4.
Eidylon
Wäre schön, wenn Google dem Einstellungsobjekt eine Formatierungszeichenfolge hinzufügen könnte.
Justin Smith
3

Wenn Sie nur den Klartextwert jedes Felds als Zusammenfassung anzeigen möchten, sollte der folgende Code am einfachsten zu pflegen sein. Es sind nur zwei Änderungen erforderlich (Zeilen 13 und 21, gekennzeichnet mit "hier ändern"):

package com.my.package;

import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;

public class PreferencesActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {

    private final String[] mAutoSummaryFields = { "pref_key1", "pref_key2", "pref_key3" }; // change here
    private final int mEntryCount = mAutoSummaryFields.length;
    private Preference[] mPreferenceEntries;

    @SuppressWarnings("deprecation")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences_file); // change here
        mPreferenceEntries = new Preference[mEntryCount];
        for (int i = 0; i < mEntryCount; i++) {
            mPreferenceEntries[i] = getPreferenceScreen().findPreference(mAutoSummaryFields[i]);
        }
    }

    @SuppressWarnings("deprecation")
    @Override
    protected void onResume() {
        super.onResume();
        for (int i = 0; i < mEntryCount; i++) {
            updateSummary(mAutoSummaryFields[i]); // initialization
        }
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); // register change listener
    }

    @SuppressWarnings("deprecation")
    @Override
    protected void onPause() {
        super.onPause();
        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); // unregister change listener
    }

    private void updateSummary(String key) {
        for (int i = 0; i < mEntryCount; i++) {
            if (key.equals(mAutoSummaryFields[i])) {
                if (mPreferenceEntries[i] instanceof EditTextPreference) {
                    final EditTextPreference currentPreference = (EditTextPreference) mPreferenceEntries[i];
                    mPreferenceEntries[i].setSummary(currentPreference.getText());
                }
                else if (mPreferenceEntries[i] instanceof ListPreference) {
                    final ListPreference currentPreference = (ListPreference) mPreferenceEntries[i];
                    mPreferenceEntries[i].setSummary(currentPreference.getEntry());
                }
                break;
            }
        }
    }

    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        updateSummary(key);
    }

}
krächzen
quelle
3

Hier ist meine Lösung:

Erstellen Sie eine Einstellungsmethode vom Typ 'getter'.

protected String getPreference(Preference x) {
    // http://stackoverflow.com/questions/3993982/how-to-check-type-of-variable-in-java
    if (x instanceof CheckBoxPreference)
        return "CheckBoxPreference";
    else if (x instanceof EditTextPreference)
        return "EditTextPreference";
    else if (x instanceof ListPreference)
        return "ListPreference";
    else if (x instanceof MultiSelectListPreference)
        return "MultiSelectListPreference";
    else if (x instanceof RingtonePreference)
        return "RingtonePreference";
    else if (x instanceof SwitchPreference)
        return "SwitchPreference";
    else if (x instanceof TwoStatePreference)
        return "TwoStatePreference";
    else if (x instanceof DialogPreference) // Needs to be after ListPreference
        return "DialogPreference";
    else
        return "undefined";
}

Erstellen Sie eine 'setSummaryInit'-Methode.

public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
        Log.i(TAG, "+ onSharedPreferenceChanged(prefs:" + prefs + ", key:" + key + ")");
        if( key != null ) {
            updatePreference(prefs, key);
            setSummary(key);
        } else {
            Log.e(TAG, "Preference without key!");
        }
        Log.i(TAG, "- onSharedPreferenceChanged()");
    }

    protected boolean setSummary() {
        return _setSummary(null);
    }

    protected boolean setSummary(String sKey) {
        return _setSummary(sKey);
    }

    private boolean _setSummary(String sKey) {
        if (sKey == null) Log.i(TAG, "Initializing");
        else Log.i(TAG, sKey);

        // Get Preferences
        SharedPreferences sharedPrefs = PreferenceManager
                .getDefaultSharedPreferences(this);

        // Iterate through all Shared Preferences
        // http://stackoverflow.com/questions/9310479/how-to-iterate-through-all-keys-of-shared-preferences
        Map<String, ?> keys = sharedPrefs.getAll();
        for (Map.Entry<String, ?> entry : keys.entrySet()) {
            String key = entry.getKey();
            // Do work only if initializing (null) or updating specific preference key
            if ( (sKey == null) || (sKey.equals(key)) ) {
                String value = entry.getValue().toString();
                Preference pref = findPreference(key);
                String preference = getPreference(pref);
                Log.d("map values", key + " | " + value + " | " + preference);
                pref.setSummary(key + " | " + value + " | " + preference);
                if (sKey != null) return true;
            }
        }
        return false;
    }

    private void updatePreference(SharedPreferences prefs, String key) {
        Log.i(TAG, "+ updatePreference(prefs:" + prefs + ", key:" + key + ")");
        Preference pref = findPreference(key);
        String preferenceType = getPreference(pref);
        Log.i(TAG, "preferenceType = " + preferenceType);
        Log.i(TAG, "- updatePreference()");
    }

Initialisieren

Erstellen Sie eine öffentliche Klasse, die PreferenceActivity und OnSharedPreferenceChangeListener implementiert

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    PreferenceManager.setDefaultValues(this, R.xml.global_preferences,
    false);
    this.addPreferencesFromResource(R.xml.global_preferences);
    this.getPreferenceScreen().getSharedPreferences()
        .registerOnSharedPreferenceChangeListener(this);
}

protected void onResume() {
    super.onResume();
    setSummary();
}
Page2PagePro
quelle
3

Einfach:

listPreference.setSummary("%s");
Oded Breiner
quelle
3

Zu Ihrer Information:

findPreference(CharSequence key)
This method was deprecated in API level 11. This function is not relevant
for a modern fragment-based PreferenceActivity.

Umso mehr Grund zu Blick auf die sehr glatt Answervon @ASD oben ( Quelle hier ) sagen zu verwenden , %sin android:summaryin für jedes Feld preferences.xml. (Der aktuelle Präferenzwert wird ersetzt %s.)

Geben Sie hier die Bildbeschreibung ein

<ListPreference
 ...        
 android:summary="Length of longest word to return as match is %s"
 ...
 />
DSlomer64
quelle
3

Da in Androidx Preference Klasse hat die SummaryProvider- Schnittstelle vorhanden ist, kann dies ohne OnSharedPreferenceChangeListener erfolgen. Für EditTextPreference und ListPreference werden einfache Implementierungen bereitgestellt. Aufbauend auf EddieBs Antwort kann es so aussehen. Getestet auf androidx.preference: Präferenz: 1.1.0-alpha03.

package com.example.util.timereminder.ui.prefs;

import android.os.Bundle;

import com.example.util.timereminder.R;

import androidx.preference.EditTextPreference;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceGroup;

/**
 * Displays different preferences.
 */
public class PrefsFragmentExample extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        addPreferencesFromResource(R.xml.preferences);

        initSummary(getPreferenceScreen());
    }

    /**
     * Walks through all preferences.
     *
     * @param p The starting preference to search from.
     */
    private void initSummary(Preference p) {
        if (p instanceof PreferenceGroup) {
            PreferenceGroup pGrp = (PreferenceGroup) p;
            for (int i = 0; i < pGrp.getPreferenceCount(); i++) {
                initSummary(pGrp.getPreference(i));
            }
        } else {
            setPreferenceSummary(p);
        }
    }

    /**
     * Sets up summary providers for the preferences.
     *
     * @param p The preference to set up summary provider.
     */
    private void setPreferenceSummary(Preference p) {
        // No need to set up preference summaries for checkbox preferences because
        // they can be set up in xml using summaryOff and summary On
        if (p instanceof ListPreference) {
            p.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
        } else if (p instanceof EditTextPreference) {
            p.setSummaryProvider(EditTextPreference.SimpleSummaryProvider.getInstance());
        }
    }
}
Razeeman
quelle
2

Hier werden alle diese aus der Eclipse-Probe geschnitten SettingsActivity . Ich muss all diese zu vielen Codes kopieren, um zu zeigen, wie diese Android-Entwickler sich perfekt für einen allgemeineren und stabileren Codierungsstil entscheiden.

Ich habe die Codes für die Anpassung an das PreferenceActivityTablet und eine größere API hinterlassen .

public class SettingsActivity extends PreferenceActivity {

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);

    setupSummaryUpdatablePreferencesScreen();
}

private void setupSummaryUpdatablePreferencesScreen() {

    // In the simplified UI, fragments are not used at all and we instead
    // use the older PreferenceActivity APIs.

    // Add 'general' preferences.
    addPreferencesFromResource(R.xml.pref_general);

    // Bind the summaries of EditText/List/Dialog preferences to
    // their values. When their values change, their summaries are updated
    // to reflect the new value, per the Android Design guidelines.
    bindPreferenceSummaryToValue(findPreference("example_text"));
    bindPreferenceSummaryToValue(findPreference("example_list"));
}

/**
 * A preference value change listener that updates the preference's summary
 * to reflect its new value.
 */
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {

    private String TAG = SettingsActivity.class.getSimpleName();

    @Override
    public boolean onPreferenceChange(Preference preference, Object value) {
        String stringValue = value.toString();

        if (preference instanceof ListPreference) {
            // For list preferences, look up the correct display value in
            // the preference's 'entries' list.
            ListPreference listPreference = (ListPreference) preference;
            int index = listPreference.findIndexOfValue(stringValue);

            // Set the summary to reflect the new value.
            preference.setSummary(
                index >= 0
                ? listPreference.getEntries()[index]
                : null);
        } else {
            // For all other preferences, set the summary to the value's
            // simple string representation.
            preference.setSummary(stringValue);
        }
        Log.i(TAG, "pref changed : " + preference.getKey() + " " + value);
        return true;
    }
};

/**
 * Binds a preference's summary to its value. More specifically, when the
 * preference's value is changed, its summary (line of text below the
 * preference title) is updated to reflect the value. The summary is also
 * immediately updated upon calling this method. The exact display format is
 * dependent on the type of preference.
 *
 * @see #sBindPreferenceSummaryToValueListener
 */

private static void bindPreferenceSummaryToValue(Preference preference) {
    // Set the listener to watch for value changes.
    preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);

    // Trigger the listener immediately with the preference's
    // current value.
    sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
                                                             PreferenceManager
                                                             .getDefaultSharedPreferences(preference.getContext())
                                                             .getString(preference.getKey(), ""));
}

}

xml/pref_general.xml

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

<!-- NOTE: EditTextPreference accepts EditText attributes. -->
<!-- NOTE: EditTextPreference's summary should be set to its value by the activity code. -->
<EditTextPreference
android:capitalize="words"
android:defaultValue="@string/pref_default_display_name"
android:inputType="textCapWords"
android:key="example_text"
android:maxLines="1"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="@string/pref_title_display_name" />

<!-- NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog todismiss it.-->
<!-- NOTE: ListPreference's summary should be set to its value by the activity code. -->
<ListPreference
android:defaultValue="-1"
android:entries="@array/pref_example_list_titles"
android:entryValues="@array/pref_example_list_values"
android:key="example_list"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="@string/pref_title_add_friends_to_messages" />

</PreferenceScreen>

values/strings_activity_settings.xml

<resources>
<!-- Strings related to Settings -->

<!-- Example General settings -->

<string name="pref_title_display_name">Display name</string>
<string name="pref_default_display_name">John Smith</string>

<string name="pref_title_add_friends_to_messages">Add friends to messages</string>
<string-array name="pref_example_list_titles">
<item>Always</item>
<item>When possible</item>
<item>Never</item>
</string-array>
<string-array name="pref_example_list_values">
<item>1</item>
<item>0</item>
<item>-1</item>
</string-array>
</resources>

HINWEIS: Eigentlich möchte ich nur kommentieren wie "Googles Beispiel für PreferenceActivity ist auch interessant". Aber ich habe nicht genug Reputationspunkte. Also bitte beschuldigen Sie mich nicht.

(Entschuldige mein schlechtes Englisch)

Johnkarka
quelle
2

Sie müssen die Funktion bindPreferenceSummaryToValue für die onCreate-Methode verwenden.

Beispiel:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Add 'general' preferences, defined in the XML file
        addPreferencesFromResource(R.xml.pref_general);

        // For all preferences, attach an OnPreferenceChangeListener so the UI summary can be
        // updated when the preference changes.
        bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key)));
        bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_units_key)));
    }

Siehe Lektion 3 zum Udacity Android-Kurs: https://www.udacity.com/course/viewer#!/c-ud853/l-1474559101/e-1643578599/m-1643578601

Pablo
quelle
2

Für EditTextPreference :

Ich bin natürlich zu dieser Lösung gekommen, nur wenn Sie eine bestimmte Edittext-Präferenz benötigen, dies aber mit jeder Präferenz tun können:

............

private static final String KEY_EDIT_TEXT_PREFERENCE2 = "on_a1";
public static  String value = "";

............

private void updatePreference(Preference preference, String key) {

            if (key.equals(KEY_EDIT_TEXT_PREFERENCE2)) {
                preference = findPreference(key);
                if (preference instanceof EditTextPreference) {
                    editTextPreference = (EditTextPreference) preference;
                    editTextPreference.setSummary(editTextPreference.getText());
                    value = editTextPreference.getText().toString();
                    return;
                }
                SharedPreferences sharedPrefs = getPreferenceManager().getSharedPreferences();
                preference.setSummary(sharedPrefs.getString(KEY_EDIT_TEXT_PREFERENCE2, ""));

            }
}

Dann in onResume ();

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

            SharedPreferences etext = getPreferenceManager().getSharedPreferences();
            String str = etext.getString("value", "");
            editTextPreference = (EditTextPreference) findPreference(KEY_EDIT_TEXT_PREFERENCE2);
            editTextPreference.setText(str);
            editTextPreference.setSummary(editTextPreference.getText());

            getPreferenceScreen().getSharedPreferences()
                    .registerOnSharedPreferenceChangeListener(this);
        }

Im:

@Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            updatePreference(findPreference(key), key);
}
Stanojkovic
quelle
2

Meine Lösung besteht darin, eine benutzerdefinierte Datei zu erstellen EditTextPreference, die in XML wie folgt verwendet wird:<com.example.EditTextPreference android:title="Example Title" />

EditTextPreference.java : -

package com.example;

import android.content.Context;
import android.util.AttributeSet;

public class EditTextPreference extends android.preference.EditTextPreference
{
    public EditTextPreference(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }

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

    public EditTextPreference(Context context)
    {
        super(context, null);
    }

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

        setSummary(getSummary());
    }

    @Override
    public CharSequence getSummary()
    {
        return getText();
    }
}
Salman von Abbas
quelle
1

ListPreferenceVerwenden Sie diesen Code, um die Zusammenfassung von a auf den in einem Dialogfeld ausgewählten Wert festzulegen:

package yourpackage;

import android.content.Context;
import android.util.AttributeSet;

public class ListPreference extends android.preference.ListPreference {

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

    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);
        if (positiveResult) setSummary(getEntry());
    }

    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        super.onSetInitialValue(restoreValue, defaultValue);
        setSummary(getEntry());
    }
}

und verweisen Sie auf das yourpackage.ListPreferenceObjekt in Ihrer preferences.xmlErinnerung, um dort anzugeben, wo android:defaultValuedies den Aufruf auslöst onSetInitialValue().

Wenn Sie möchten, können Sie den Text ändern, bevor Sie die setSummary()für Ihre Anwendung geeignete Option aufrufen .

gicci
quelle
1

Da ich einen benutzerdefinierten Benutzer verwende PreferenceDataStore, kann ich einigen keinen Listener hinzufügen, SharedPreferencedaher musste ich eine etwas hackige Lösung schreiben, die auf jede Einstellung hört:

class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChangeListener {
    private val handler: Handler by lazy { Handler(Looper.getMainLooper()) }

    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        preferenceManager.preferenceDataStore = prefs
        addPreferencesFromResource(R.xml.app_preferences)
        onPreferenceChange(preferenceScreen, null)
    }

    override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
        preference.onPreferenceChangeListener = this

        when (preference) {
            is PreferenceGroup -> for (i in 0 until preference.preferenceCount) {
                onPreferenceChange(preference.getPreference(i), null)
            }
            is ListPreference -> {
                if (preference.value == null) {
                    preference.isPersistent = false
                    preference.value = Preference::class.java.getDeclaredField("mDefaultValue")
                            .apply { isAccessible = true }
                            .get(preference).toString()
                    preference.isPersistent = true
                }

                postPreferenceUpdate(Runnable { preference.summary = preference.entry })
            }
        }
        return true
    }

    /**
     * We can't directly update the preference summary update because [onPreferenceChange]'s result
     * is used to decide whether or not to update the pref value.
     */
    private fun postPreferenceUpdate(r: Runnable) = handler.post(r)
}
SUPERCILEX
quelle
1

Wenn Sie AndroidX verwenden, können Sie eine benutzerdefinierte verwendenSummaryProvider . Dieser Ansatz kann für jeden verwendet werden Preference.

Beispiel aus der Dokumentation (Java):

EditTextPreference countingPreference = (EditTextPreference) findPreference("counting");

countingPreference.setSummaryProvider(new SummaryProvider<EditTextPreference>() {
    @Override
    public CharSequence provideSummary(EditTextPreference preference) {
        String text = preference.getText();
        if (TextUtils.isEmpty(text)){
            return "Not set";
        }
        return "Length of saved value: " + text.length();
    }
});

Beispiel aus der Dokumentation (Kotlin):

val countingPreference = findPreference("counting") as EditTextPreference

countingPreference.summaryProvider = SummaryProvider<EditTextPreference> { preference ->
    val text = preference.text
    if (TextUtils.isEmpty(text)) {
        "Not set"
    } else {
        "Length of saved value: " + text.length
    }
}
Andrew Churilo
quelle