Android Tercihinin geçerli değerini Tercihler özetinde nasıl görüntülerim?


457

Bu çok sık ortaya çıkmalı.

Kullanıcı bir Android uygulamasında tercihleri ​​düzenlerken, tercihin o anda ayarlanan değerini Preferenceözette görebilmelerini istiyorum .

Örnek: "Eski iletileri sil" için, iletilerin temizlenmesi gereken gün sayısını belirten bir Tercih ayarım varsa. Gelen PreferenceActivitygörmek için kullanıcı istiyorum:

"Eski mesajları sil" <- title

"İletileri x gün sonra temizle " <- özet, burada x geçerli Tercih değeridir

Ekstra kredi: bu yeniden kullanılabilir olun, böylece kolayca kendi türüne bakmaksızın tüm tercihlerime uygulayabilirsiniz (böylece minimum miktarda kodlama ile EditTextPreference, ListPreference vb ile çalışır).

Yanıtlar:


151

İhtiyaçlarınıza uygunsa, bunu daha genel bir çözüm haline getirmenin yolları vardır.

Örneğin, genel olarak tüm liste tercihlerinin seçimlerini özet olarak göstermesini istiyorsanız, onSharedPreferenceChangeduygulamanız için buna sahip olabilirsiniz :

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

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

Bu, diğer tercih sınıflarına kolayca genişletilebilir.

Ve kullanarak getPreferenceCountve getPreferenceişlevselliği PreferenceScreenve PreferenceCategorykolayca onların arzu türleri tercihleri özetleri ayar tercihi ağacı yürümeye genel bir fonksiyon yazabiliriz toStringtemsil


6
gerçekten güzel bir çözüm. sadece bir başlatma yok
njzk2

9
@ njzk2 yapmanız gereken tek şey etkinlik olduğundan emin olmaktırimplements OnSharedPreferenceChangeListener

4
Not: Daha basit bir yol var, bkz. @ Robertas'ın cevabı .
Salman von Abbas

6
Aslında, hiç özetini ayarlayabilirsiniz "%s"için ListPreferenceve ListPreference.getSummary()seçilen geçerli girişle özetini biçimlendirir (veya ""eğer hiçbiri seçili).
SOFe

findPreference (key) kullanımdan kaldırıldı, buna erişmenin başka bir yolu var mı?
Nevermore

144

İşte benim çözümüm ... 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());
        }
    }
}

@DdieB ... bu harika çalışıyor, ancak bir tercih ekranı içinde bir tercih ekranı var. İç tercih ekranına nasıl ulaşılacağı ve özetle nasıl doldurulacağı hakkında bir fikriniz var mı?
taraloca

@taraloca - eğer değiştirirse (p instanceof PreferenceCategory) {PreferenceCategory pCat = (PreferenceCategory) p; - if (p instanceof PreferenceGroup) {final PreferenceGroup pCat = (PreferenceGroup) p;
Martin Ždila

eğer bu ne çalışıyor harika EditTextPreferenceolduğunu android:password="true" o değerini gösterir
Chathura Wijesinghe

1
Tanımlanmış bir değer yoksa (yani if editTextPref.getText() == "") kaynak (xml) dosyasından özet görüntülemek için kodu nasıl değiştirmeliyim ? Özet değeri nasıl alınır updatePrefSummary? p.getSummary()ve editTextPref.getSummary()zaten değiştirilmiş değerleri döndürür.
LA_

Her iki yana PreferenceCategoryve PreferenceScreengelen inherit PreferenceGroup, ben değiştim initSummarybir idare PreferenceGroupyerine. Bu, başka bir döngü ihtiyacını önler onCreate(). Davranış değişikliği: yuvalanmış PreferenceScreens artık yinelemeli olarak da ele alınmaktadır.
Lekensteyn

96

Android dokümantasyonu , bir kişinin bir Dize biçimlendirme işaretçisi kullanabileceğini söylüyor getSummary():

Özette bir Dize biçimlendirme işareti varsa (yani "% s" veya "% 1 $ s"), geçerli giriş değeri onun yerine kullanılır.

android:summary="Clean up messages after %s days"ListPreference xml bildiriminde belirtmek benim için çalıştı.

Not: Bu sadece çalışır ListPreference.


Birisi yanılıyorsam beni düzeltir, ancak getSummary () belgeleri API düzeyi 1'de eklendiğini belirtir. İlk yayınlandığında davranışın farklı olduğunu ima ediyor musunuz?
TheIT

10
Ne yazık ki, bu sadece ListPreference için çalışır. Aynı davranışı EditTextPreference için istiyorum. Google'ın bunu tüm DialogPreferences için eklememesi şaşırtıcıdır.
Vicki

2
Ayrıca, değer ayarlanmadığı sürece çalışmaz - Tercih etkinliğinin ilk çağrısında, sadece% s görüntüler ve bu gerçekten aptalcadır.
Zordid

3
@Zordid Bu, xml'nizdeki ListPreference'deki gibi varsayılan değer belirtilerek android:defaultValue="0"düzeltilebilir. Bu en mantıklı cevap ve benim için çalışıyor.
Mohit Singh

@Mohit Singh / @Zordid, Lollipop API 22'de defaultValueve %sçalışmıyor. Diğer sürümlerde, genel olarak, olsa da çalışır. Herhangi bir çözüm lütfen? Bunun için özel bir sınıf yazmak istemiyorum. Google'ın bu kadar acı verici görevleri en önemsiz hale getirmesi inanılmaz.
Narayana J

81

Eğer kullanırsan PreferenceFragment, ben böyle çözdüm. Kendini açıklayıcı.

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

3
Bu çözümün daha fazla oy alması gerekiyor ... Bana geliştirici sitesindeki örneklerin bunu GÖSTERDİĞİNİ, ancak tamamen atladığını söylüyor.
Justin Smith

3
EditTextPreferences da güncellenmiş almak için bunu updatePreferenceCODE if (preference instanceof EditTextPreference) { EditTextPreference editTextPref = (EditTextPreference) preference; preference.setSummary(editTextPref.getText()); }teşekkürler @EddieB ekleyin
Eugene van der Merwe

6
Nereyi unregisterOnSharedPreferenceChangeListenerarıyorsun?
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 Ne alıntı yaptığınızın farkındayım. Bu, kullanmamanızı PreferenceActivity.findPreference(ve diğer birkaç yöntemi) söylemektir , çünkü Google, bunun PreferenceFragment.findPreferenceyerine bu yanıtta gösterilen tekniğe geçmenizi ister .
Dan Hulme

33

Benim seçeneğim ListPreference genişletmek ve temiz:

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

Ardından settings.xml dosyasına eklersiniz:

<yourpackage.ListPreferenceShowSummary
    android:key="key" android:title="title"
    android:entries="@array/entries" android:entryValues="@array/values"
    android:defaultValue="first value"/>

Buna dayanarak bir çözüm yaptım. Benim çözümde hem menü hem de özetleri giriş dizeleri kullanmak yerine entrySummaries bir dizi ayarlamak için bir yöntem var. Burada bir sorun var: getEntry () yeni değeri değil, önceki değeri döndürür.
pzulw

1
Aslında init () nescessary bile mi? Ben getSummary () overidden var ve kaymakam gibi görünüyor!
Andy

4
En yüksek oyu alandan çok daha kolay ve temiz bir çözüm gibi görünüyor!
muslidrikk

2
init()Fonksiyon güncellemek için gerekli olan summarykullanıcı bu tercihi değiştirdiğinde. Bu olmadan, giriş başlangıçta ne olursa olsun kalacak.
anthonylawson

23

Varsayılan Tercih sınıflarını geçersiz kılabilir ve özelliği uygulayabilirsiniz.

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

Daha sonra xml içinde özel tercihleri ​​kullanabilirsiniz

<your.package.name.MyListPreference 
    android:key="noteInterval"
    android:defaultValue="60"
    android:title="Notification Interval"
    android:entries="@array/noteInterval"
    android:entryValues="@array/noteIntervalValues"
    />

Mükemmel basit yöntem. Sorunlara neden olabileceği için (veya benim için yaptıkları gibi) getEntry dizesinde% gibi şeylere dikkat edin
Andrew

21

Birkaç saat sonra böyle bir sorunu çözmek için harcanan bu kodu uyguladım:

[GÜNCELLEME: son sürüm listesi]

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

Benim için işe yarayan tek çözüm buydu. ListPreferences alt sınıflandırma ve android uygulamak için önce: özet = "bla bla bla% s". İkisi de işe yaramadı.


Yolunuz daha net ve diğerlerinden daha az kod kullanıyor. En iyi yanıtlar "proxy" - tercihler yöneticisi kullanılarak çalışır. Listedeki doğrudan değişiklikleri dinlemek o kadar net değil.
Paul Annekov

@Subtle Fox, Düzgün bir çözüm. sadece 'setDefaultValue ()' yapıp yapmadığınızı merak ediyorsanız neden kontrol edin (ss == null)
Samuel

Çünkü setDefaultValue () orada olmamalı :)
Yeniden düzenleme

20

Belki ListPreference gibi: İstediğinizi almak için getSummary'yi değiştirin:

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

Ve bunu xml'nizde kullanın:

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

Böylece %sgerçek değer yerine bir özet yazabilirsiniz .


1
@Eruvanos @ serv-inc En azından bir alt sınıfında android.support.v7.preference.EditTextPreferencebu, tercih değiştirildiğinde, yalnızca tercihler etkinliği oluşturulduğunda özeti güncelleştirmez. OnSharedPreferenceChangeListener.onSharedPreferenceChangedTercihler fragman sınıfında uygulamadan bunun bir yolu da geçersiz android.support.v7.preference.EditTextPreference.setText(String text)@Override public void setText(String text) { super.setText(text); this.setSummary(this.getText()); }
kılmaktır

@PointedEars: bitti. Ancak bu aynı zamanda stackoverflow.com/a/21906829/1587329
serv-inc

18

Bu, özeti seçilen değere ayarlamanız için gereken koddur. Ayrıca başlangıçta değerleri ayarlar ve yalnızca değişikliklere değil, varsayılan değerlere de uyar. "R.layout.prefs" dosyasını xml dosyanızla değiştirin ve setSummary yöntemini ihtiyaçlarınıza göre genişletin. Aslında sadece ListPreferences kullanıyor, ancak diğer Tercihlere uyacak şekilde özelleştirmek kolaydır.

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


Çok teşekkürler! Ben onCreate () bir argüman olarak kaynak kimliği vererek bundan bir sınıf oluşturdum - bu şekilde ayarları özet olarak değerleri göstermek için ayarları ekranlarımda bir satır değişiklik oldu.
Asmo Soinio

2
BTW: Kalıcı olmayan tercihlerin bu sistem kullanılarak güncellenmeyeceğini unutmayın. Bunlardaki değişiklikler setOnPreferenceChangeListener(Preference.OnPreferenceChangeListener onPreferenceChangeListener), bireysel Tercihlerin yöntemi kullanılarak dinlenmelidir .
Asmo Soinio

11

Aslında, CheckBoxPreference , onay kutusu değerine bağlı olarak farklı bir özet belirtebilir. Android: özetOff ve android: özetOn özniteliklerine (karşılık gelen CheckBoxPreference yöntemleri) bakın.


11

EditTextPreference için:

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

9

Birisi hala buna cevap arıyorsa, otuzüçüncü sorunun cevabını kontrol etmelisiniz .

<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,% s yerine ListPreference seçicisi tarafından görüntülenen geçerli dize değerini kullanır.


İşler. Bu bugün en kolay ve en iyi çözümdür.
davidgyoung

1
"% S" ifadesinin özet dizenizin herhangi bir yerine yerleştirilebileceğini unutmayın. Ve evet, bu kaynak dizelerini içerir!
Scott Biggs

7

Bu ipucu için teşekkürler!

Bir tercih ekranım var ve her liste tercihinin değerini özet olarak göstermek istiyorum.

Şimdi bu benim yolum:

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

Bu benim için çalışıyor, ama merak ediyorum en iyi çözüm nedir (performans, istikrar, ölçeklenebilirlik): Koem'in gösterdiği veya bu olduğu?


6

Ayrıntılı açıklama için teşekkürler, Reto!

Bu kimseye herhangi bir yardımcı olması durumunda, Android 1.5 için SDK ile çalışması için Reto Meier tarafından önerilen kodu değiştirmek zorunda kaldı

@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            
    ...
}

Aynı değişiklik geri arama işlevi için de geçerlidir onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)

Alkış,

Chris


4

Aşağıdaki ListPreference soyundan sorunu çözdüm:

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

1.6.4 ile 4.0.4 arasında benim için iyi çalışıyor gibi görünüyor.


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

4

Oylanan tüm cevapların, özetin tam olarak geçerli değerle nasıl ayarlanacağını gösterdiğini gördüm, ancak OP de şöyle bir şey istedi:

"İletileri x gün sonra temizle " * <- özet, burada x geçerli Tercih değeridir

İşte bunu başarmak için cevabım

Belgelerin dediği gibi ListPreference.getSummary():

Bu ListPreference özetini döndürür. Özette bir Dize biçimlendirme işareti varsa (yani "% s" veya "% 1 $ s"), geçerli giriş değeri onun yerine kullanılır.

Ancak, birkaç cihazda denedim ve işe yaramıyor gibi görünüyor. Biraz araştırma yaparak, bu cevapta iyi bir çözüm buldum . Sadece Preferencekullandığınız her şeyi genişletmek ve getSummary()Android belgelerinde belirtilen şekilde geçersiz kılmaktan oluşur .


1
Başlangıçta çalışıyor gibi görünüyor, ancak yeni bir değer seçtiğinizde, tüm etkinliği geçersiz kılmak ve yeniden çizilmesine neden olacak bir şey yapana kadar otomatik olarak güncellenmez. Android 4.0.4 kullanıyorum.
eidylon

Google tercih nesnesine bir biçimlendirme dizesi ekleyebilseydi iyi olur.
Justin Smith

3

Her alanın düz metin değerini yalnızca özet olarak görüntülemek istiyorsanız, aşağıdaki kodun bakımı en kolay yöntem olmalıdır. Yalnızca iki değişiklik gerektirir ("burada değiştir" ile işaretlenmiş 13 ve 21 satırları):

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

}

3

İşte benim çözümüm:

Bir tercih türü 'getter' yöntemi oluşturun.

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

Bir 'setSummaryInit' yöntemi oluşturun.

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

Başlatma

PreferenceActivity'nin uyguladığı ve OnSharedPreferenceChangeListener uygulayan genel bir sınıf oluşturun

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


3

Bilginize:

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

Çok kaygan bakmak için bir sebep daha Answeryukarıda @ASD ait ( kaynak burada bulunan kullanmaya söyleyerek) %siçinde android:summaryher alan için preferences.xml. (Geçerli tercih değeri ikame edilir %s.)

resim açıklamasını buraya girin

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

3

Androidx'te Preference sınıfı SummaryProvider arabirimine sahip olduğundan, OnSharedPreferenceChangeListener olmadan yapılabilir. EditTextPreference ve ListPreference için basit uygulamalar sağlanır. Bina EddieB cevabı böyle bakabilirsiniz. Androidx üzerinde test edilmiştir. Tercih: tercih: 1.1.0-alfa03.

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

3

Göre Android docs kullanabileceğiniz app:useSimpleSummaryProvider="true"ListPreference ve EditTextPreference bileşenlerindeki.


2

Burada, bunların hepsi Eclipse örneğinden kesilir SettingsActivity. Bu android geliştiricilerinin daha genel ve kararlı kodlama stili için mükemmel bir şekilde nasıl seçtiklerini göstermek için tüm bu çok fazla kodu kopyalamak zorundayım.

PreferenceActivityTablete ve daha büyük API'ye uyarlamak için kodları bıraktım .

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>

NOT: Aslında "Google'ın PreferenceActivity için örneği de ilginç" gibi yorum yapmak istiyorum. Ama yeterince itibar puanım yok, bu yüzden lütfen beni suçlama.

(Kötü İngilizce için özür dilerim)


2

OnCreate yönteminde bindPreferenceSummaryToValue işlevini kullanmanız gerekir.

Misal:

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

Udacity Android Kursu 3. dersine bakın: https://www.udacity.com/course/viewer#!/c-ud853/l-1474559101/e-1643578599/m-1643578601


2

İçin EditTextPreference :

Bu çözüme, elbette, belirli bir düzenleme metni tercihine ihtiyacınız varsa geldim, ancak bunu her Tercih ile yapabilirsiniz:

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

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, ""));

            }
}

Sonra onResume () 'de;

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

İçinde:

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

2

Benim çözüm EditTextPreferenceXML gibi kullanılan bir özel oluşturmaktır :<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();
    }
}

1

A özetini ListPreferencebir iletişim kutusunda seçilen değere ayarlamak için şu kodu kullanabilirsiniz:

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

ve çağrınızdaki tetikleyiciyi orada belirtmek yourpackage.ListPreferenceiçin preferences.xmlhatırlamanızdaki nesneye bakın .android:defaultValueonSetInitialValue()

İsterseniz setSummary()uygulamanız için uygun olanı aramadan önce metni değiştirebilirsiniz .


1

Bir özel kullandığım için PreferenceDataStore, bazılarına dinleyici ekleyemiyorum, SharedPreferencebu yüzden her tercihi dinleyen biraz hileli bir çözüm yazmak zorunda kaldım:

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

1

AndroidX kullanıyorsanız bir özel kullanabilirsinizSummaryProvider . Bu yaklaşım herhangi biri için kullanılabilir Preference.

Belgelerden örnek (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();
    }
});

Belgelerden örnek (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
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.