Bagaimana cara menampilkan nilai Preferensi Android saat ini di ringkasan Preferensi?

457

Ini harus sering muncul.

Saat pengguna mengedit preferensi di aplikasi Android, saya ingin mereka dapat melihat nilai preferensi yang saat ini ditetapkan dalam Preferenceringkasan.

Contoh: jika saya memiliki pengaturan Preferensi untuk "Buang pesan lama" yang menentukan jumlah hari setelah mana pesan perlu dibersihkan. Dalam PreferenceActivitySaya ingin pengguna melihat:

"Buang pesan lama" <- judul

"Bersihkan pesan setelah x hari" <- ringkasan di mana x adalah nilai Preferensi saat ini

Kredit ekstra: buat ini dapat digunakan kembali, jadi saya dapat dengan mudah menerapkannya ke semua preferensi saya terlepas dari jenisnya (sehingga bekerja dengan EditTextPreference, ListPreference dll. Dengan jumlah pengkodean minimal).

nyenyec
sumber

Jawaban:

151

Ada beberapa cara untuk menjadikan ini solusi yang lebih umum, jika itu sesuai dengan kebutuhan Anda.

Misalnya, jika Anda ingin secara umum semua preferensi daftar menunjukkan pilihan mereka sebagai ringkasan, Anda bisa memiliki ini untuk onSharedPreferenceChangedimplementasi Anda :

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

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

Ini mudah diperluas ke kelas preferensi lainnya.

Dan dengan menggunakan getPreferenceCountdan getPreferencefungsionalitas dalam PreferenceScreendan PreferenceCategory, Anda dapat dengan mudah menulis fungsi generik untuk berjalan di pohon preferensi pengaturan ringkasan semua preferensi dari jenis yang Anda inginkan untuk toStringrepresentasi mereka.

DozenCrows
sumber
6
solusi yang bagus memang. hanya tidak memiliki inisialisasi
njzk2
9
@ njzk2 yang harus Anda lakukan adalah memastikan aktivitasimplements OnSharedPreferenceChangeListener
4
NB: Ada cara yang lebih sederhana, lihat jawaban @ Robertas .
Salman von Abbas
6
Sebenarnya, Anda dapat mengatur ringkasan "%s"untuk ListPreference, dan ListPreference.getSummary()akan memformat ringkasan dengan entri yang dipilih saat ini (atau ""jika tidak ada yang dipilih).
SOFe
findPreference (kunci) sudah usang, apakah ada cara lain untuk mengakses ini?
Nevermore
144

Inilah solusi saya ... 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
sumber
Ini berfungsi dengan baik @EddieB ... kecuali saya memiliki layar preferensi di dalam layar preferensi. Adakah yang tahu bagaimana mencapai layar preferensi dalam dan mengisinya dengan ringkasan?
taraloca
@taraloca - ubah if (p instanceof PreferenceCategory) {PreferenceCategory pCat = (PreferenceCategory) p; to if (p instanceof PreferenceGroup) {final PreferenceGroup pCat = (PreferenceGroup) p;
Martin Ždila
besar ini bekerja bagaimana jika EditTextPreferenceyang android:password="true" menunjukkan nilai
Chathura Wijesinghe
1
Bagaimana saya harus memodifikasi kode untuk menampilkan ringkasan dari file sumber daya (xml) jika tidak ada nilai yang didefinisikan (yaitu if editTextPref.getText() == "")? Bagaimana cara mendapatkan nilai ringkasan updatePrefSummary? p.getSummary()dan editTextPref.getSummary()mengembalikan nilai yang sudah dimodifikasi.
LA_
Karena keduanya PreferenceCategorydan PreferenceScreenmewarisi dari PreferenceGroup, saya telah berubah initSummaryuntuk menangani PreferenceGroup. Ini menghindari perlunya loop lain di onCreate(). Perubahan perilaku: PreferensiScreens bersarang sekarang juga dapat ditangani secara rekursif.
Lekensteyn
96

Dokumentasi Android mengatakan seseorang dapat menggunakan penanda pemformatan String di getSummary():

Jika ringkasan memiliki penanda pemformatan String di dalamnya (yaitu "% s" atau "% 1 $ s"), maka nilai entri saat ini akan diganti di tempatnya.

Cukup menentukan android:summary="Clean up messages after %s days"dalam deklarasi ListPreference xml bekerja untuk saya.

Catatan: Ini hanya berfungsi untuk ListPreference.

Robertas
sumber
Seseorang mengoreksi saya jika saya salah, tetapi dokumentasi untuk getSummary () menyatakan bahwa itu ditambahkan di API level 1. Apakah Anda menyiratkan bahwa perilaku itu berbeda ketika pertama kali dirilis?
TheIT
10
Sayangnya, ini hanya berfungsi untuk ListPreference. Saya ingin perilaku yang sama untuk EditTextPreference. Sangat mengejutkan bahwa Google belum menambahkan ini untuk semua DialogPreferences.
Vicki
2
Plus, saya tidak bekerja selama nilainya belum ditetapkan - pada panggilan pertama aktivitas Preferensi, ini hanya menampilkan% s yang benar-benar bodoh.
Zordid
3
@Zordid Itu bisa diperbaiki dengan menentukan nilai default di xml Anda seperti android:defaultValue="0"di ListPreference Anda. Ini adalah jawaban yang paling masuk akal dan berfungsi untuk saya.
Mohit Singh
@Mohit Singh / @Zordid, di Lollipop API 22, defaultValuedan yang %stidak berfungsi. Pada versi lain, umumnya, ini berfungsi. Ada solusi, tolong? Saya yakin tidak ingin menulis kelas khusus untuk ini. Sulit dipercaya bahwa Google membuat tugas yang paling sepele seperti menyakitkan.
Narayana J
81

Jika Anda menggunakan PreferenceFragment, ini adalah bagaimana saya menyelesaikannya. Cukup jelas.

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
sumber
3
Solusi ini membutuhkan lebih banyak suara ... Itu mengganggu saya bahwa contoh di situs pengembang MENUNJUKKAN ini sedang dilakukan, tetapi hilangkan sepenuhnya.
Justin Smith
3
Untuk mendapatkan EditTextPreferences juga diperbarui, tambahkan ini ke updatePreferenceCODE if (preference instanceof EditTextPreference) { EditTextPreference editTextPref = (EditTextPreference) preference; preference.setSummary(editTextPref.getText()); }terima kasih @EddieB
Eugene van der Merwe
6
Di mana Anda menelepon 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 Saya sangat tahu apa yang Anda kutip. Ia memberi tahu Anda untuk tidak menggunakan PreferenceActivity.findPreference(dan beberapa metode lain), karena Google ingin Anda beralih ke teknik yang ditunjukkan dalam jawaban ini, yang menggunakan PreferenceFragment.findPreferencesebaliknya.
Dan Hulme
33

Opsi saya adalah memperluas ListPreference dan bersih:

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

Kemudian Anda tambahkan di settings.xml Anda:

<yourpackage.ListPreferenceShowSummary
    android:key="key" android:title="title"
    android:entries="@array/entries" android:entryValues="@array/values"
    android:defaultValue="first value"/>
Kamu punya budak
sumber
Saya membuat solusi berdasarkan ini. Dalam solusi saya, saya memiliki metode untuk mengatur array entrySummaries daripada menggunakan string entri di menu dan ringkasan. Ada satu masalah di sini: getEntry () mengembalikan nilai sebelumnya bukan yang baru.
pzulw
1
Sebenarnya init () bahkan perlu? Saya baru saja menggunakan getSummary () dan tampaknya berfungsi dengan sempurna!
Andy
4
Tampaknya solusi yang jauh lebih mudah dan lebih bersih daripada yang tertinggi!
muslidrikk
2
The init()Fungsi ini diperlukan untuk memperbarui summaryketika pengguna mengubah preferensi itu. Tanpa itu, itu hanya akan tinggal apa pun entri awalnya.
anthonylawson
23

Anda dapat mengganti kelas Preferensi default dan mengimplementasikan fitur.

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

Kemudian pada Anda xml, Anda dapat menggunakan preferensi khusus seperti

<your.package.name.MyListPreference 
    android:key="noteInterval"
    android:defaultValue="60"
    android:title="Notification Interval"
    android:entries="@array/noteInterval"
    android:entryValues="@array/noteIntervalValues"
    />
Palani
sumber
Metode sederhana yang luar biasa. Hanya hati-hati untuk hal-hal seperti% dalam string getEntry karena mereka dapat menyebabkan masalah (atau mereka lakukan untuk saya)
Andrew
21

Setelah beberapa jam saya dihabiskan untuk menyelesaikan masalah seperti itu saya telah menerapkan kode ini:

[UPDATE: daftar versi final]

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

Itu adalah satu-satunya solusi yang bekerja untuk saya dengan baik. Sebelumnya saya sudah mencoba subclass dari ListPreferences dan mengimplementasikan android: summary = "bla bla bla% s". Tidak ada yang berhasil.

Rubah Halus
sumber
Cara Anda lebih jelas dan menggunakan lebih sedikit kode daripada yang lain. Jawaban teratas berfungsi menggunakan "proxy" - preferensi manajer. Tidak begitu jelas mendengarkan perubahan langsung dalam daftar.
Paul Annekov
@Subtle Fox, solusi Rapi. hanya ingin tahu jika Anda melakukan 'setDefaultValue ()' lalu mengapa memeriksa (ss == null)
Samuel
Karena setDefaultValue () seharusnya tidak ada di sana :) Saya sudah meletakkan kode ini sebelum refactoring
Subtle Fox
20

Mungkin seperti ListPreference: Ubah getSummary untuk mendapatkan yang Anda inginkan:

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

Dan gunakan ini di xml Anda:

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

Jadi, Anda dapat menulis ringkasan dengan %sbukan nilai sebenarnya.

Eruvanos
sumber
1
@Eruvanos @ serv-inc Setidaknya dengan subkelas dari android.support.v7.preference.EditTextPreference, ini tidak memperbarui ringkasan ketika preferensi diubah, hanya ketika aktivitas preferensi dibuat. Cara mengatasi hal ini tanpa menerapkan OnSharedPreferenceChangeListener.onSharedPreferenceChangeddalam kelas fragmen preferensi adalah juga menimpa android.support.v7.preference.EditTextPreference.setText(String text):@Override public void setText(String text) { super.setText(text); this.setSummary(this.getText()); }
PointedEars
@PointedEars: selesai. Tetapi ini juga tampaknya merupakan salinan dari stackoverflow.com/a/21906829/1587329
serv-inc
18

Ini adalah kode yang Anda butuhkan untuk mengatur ringkasan ke nilai yang dipilih. Ini juga menetapkan nilai-nilai pada saat startup dan menghormati nilai-nilai default, tidak hanya pada perubahan. Cukup ubah "R.layout.prefs" ke file xml Anda dan perluas metode setSummary sesuai kebutuhan Anda. Ini sebenarnya hanya menangani ListPreferences, tetapi mudah untuk menyesuaikan agar menghargai Preferensi lain.

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
sumber
Terima kasih banyak! Saya membuat kelas dari ini, memberikan id sumber daya sebagai argumen untuk onCreate () - dengan cara itu satu perubahan baris ke layar pengaturan saya agar mereka menunjukkan nilai dalam ringkasan.
Asmo Soinio
2
BTW: Perhatikan bahwa preferensi tidak persisten tidak akan diperbarui menggunakan sistem ini. Perubahan pada mereka harus didengarkan menggunakan setOnPreferenceChangeListener(Preference.OnPreferenceChangeListener onPreferenceChangeListener)-metode Preferensi individual.
Asmo Soinio
11

Sebenarnya, CheckBoxPreference memang memiliki kemampuan untuk menentukan ringkasan berbeda berdasarkan nilai kotak centang. Lihat atribut android: summaryOff dan android: summaryOn (serta metode CheckBoxPreference yang sesuai).

dhaag23
sumber
11

Untuk 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
sumber
9

Jika seseorang masih mencari jawaban untuk ini, Anda harus memeriksa jawaban tiga puluh tiga .

<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 akan mengganti% s dengan nilai string preferensi saat ini, seperti yang ditampilkan oleh pemilih ListPreference.

Iritator
sumber
Bekerja Ini adalah solusi termudah dan terbaik saat ini.
davidgyoung
1
Perhatikan bahwa "% s" dapat ditempatkan di mana saja di string ringkasan Anda. Dan ya, itu termasuk rangkaian sumber daya!
Scott Biggs
7

Terima kasih atas tip ini!

Saya memiliki satu layar preferensi dan ingin menunjukkan nilai untuk setiap preferensi daftar sebagai ringkasan.

Ini cara saya sekarang:

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

Ini bekerja untuk saya, tapi saya bertanya-tanya apa solusi terbaik (kinerja, stabilitas, skalibilitas): yang Koem tunjukkan atau yang ini?

alexx
sumber
6

Terima kasih, Reto, untuk penjelasan terperinci!

Dalam hal ini dapat membantu siapa pun, saya harus mengubah kode yang diusulkan oleh Reto Meier agar berfungsi dengan SDK untuk Android 1.5

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

Perubahan yang sama berlaku untuk fungsi panggilan balik onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)

Bersulang,

Chris

Chris
sumber
4

Saya memecahkan masalah dengan keturunan ListPreference berikut:

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

Tampaknya bekerja dengan baik untuk saya dalam 1,6 hingga 4,0,4.

Paman Kode Monyet
sumber
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
sumber
4

Saya telah melihat semua jawaban memberi suara menunjukkan cara mengatur ringkasan dengan nilai saat ini yang tepat, tetapi OP juga menginginkan sesuatu seperti:

"Bersihkan pesan setelah x hari" * <- ringkasan di mana x adalah nilai Preferensi saat ini

Inilah jawaban saya untuk mencapainya

Seperti yang dikatakan dokumentasi tentang ListPreference.getSummary():

Mengembalikan ringkasan ListPreference ini. Jika ringkasan memiliki penanda pemformatan String di dalamnya (yaitu "% s" atau "% 1 $ s"), maka nilai entri saat ini akan diganti di tempatnya.

Namun, saya mencoba beberapa perangkat dan sepertinya tidak berhasil. Dengan beberapa penelitian, saya menemukan solusi yang baik dalam jawaban ini . Ini hanya terdiri dari memperluas setiap PreferenceAnda menggunakan dan menimpa getSummary()untuk bekerja sebagaimana ditentukan oleh dokumentasi Android.

Christian García
sumber
1
Tampaknya memang bekerja pada awalnya, tetapi ketika Anda memilih nilai baru itu tidak secara otomatis memperbarui sampai Anda melakukan sesuatu untuk membatalkan seluruh aktivitas dan menyebabkannya digambar ulang. Saya menggunakan Android 4.0.4.
eidylon
Akan lebih baik jika Google dapat menambahkan string pemformatan ke objek preferensi.
Justin Smith
3

Jika Anda hanya ingin menampilkan nilai teks biasa dari masing-masing bidang sebagai rangkumannya, kode berikut ini harus paling mudah dipertahankan. Ini hanya membutuhkan dua perubahan (baris 13 dan 21, ditandai dengan "ubah di sini"):

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

}
gak
sumber
3

Inilah solusi saya:

Buat metode 'pengambil' jenis preferensi.

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

Bangun metode 'setSummaryInit'.

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

Inisialisasi

Buat kelas publik yang PreferenceActivity dan mengimplementasikan OnSharedPreferenceChangeListener

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
sumber
3

Secara sederhana:

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

FYI:

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

Semua alasan lagi untuk melihat slick Answerdari @ ASD di atas ( sumber ditemukan di sini ) mengatakan untuk digunakan %sdalam android:summaryuntuk setiap bidang dalam preferences.xml. (Nilai preferensi saat ini diganti untuk %s.)

masukkan deskripsi gambar di sini

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

Karena di androidx Preference kelas memiliki antarmuka SummaryProvider , itu dapat dilakukan tanpa OnSharedPreferenceChangeListener. Implementasi sederhana disediakan untuk EditTextPreference dan ListPreference. Membangun jawaban EddieB bisa terlihat seperti ini. Diuji pada androidx.preference: preferensi: 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());
        }
    }
}
Peramal
sumber
3

Menurut dokumen Android yang dapat Anda gunakan app:useSimpleSummaryProvider="true"dalam komponen ListPreference dan EditTextPreference.

alishir
sumber
2

Di sini, semua ini dipotong dari sampel Eclipse SettingsActivity. Saya harus menyalin semua kode ini terlalu banyak untuk menunjukkan bagaimana pengembang android ini memilih dengan sempurna untuk gaya pengkodean yang lebih umum dan stabil.

Saya meninggalkan kode untuk mengadaptasi PreferenceActivitytablet ke dan API yang lebih besar.

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>

CATATAN: Sebenarnya saya hanya ingin berkomentar seperti "Sampel Google untuk PreferenceActivity juga menarik". Tapi saya tidak punya poin reputasi yang cukup. Jadi tolong jangan salahkan saya.

(Maaf untuk bahasa Inggris yang buruk)

johnkarka
sumber
2

Anda harus menggunakan fungsi bindPreferenceSummaryToValue pada metode onCreate.

Contoh:

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

Lihat pelajaran 3 tentang Udacity Android Course: https://www.udacity.com/course/viewer#!/c-ud853/l-1474559101/e-1643578599/m-1643578601

Pablo
sumber
2

Untuk EditTextPreference :

Saya datang ke solusi ini, tentu saja, hanya jika Anda memerlukan preferensi edittext tertentu tetapi Anda bisa melakukan ini dengan setiap Preferensi:

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

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

            }
}

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

Di:

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

Solusi saya adalah membuat custom EditTextPreference, digunakan dalam XML seperti ini:<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
sumber
1

Untuk mengatur ringkasan a ListPreferenceke nilai yang dipilih dalam dialog, Anda dapat menggunakan kode ini:

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

dan referensi yourpackage.ListPreferenceobjek dalam preferences.xmlingatan Anda untuk menentukan di sana Anda android:defaultValuekarena ini memicu panggilan untuk onSetInitialValue().

Jika mau, Anda dapat memodifikasi teks sebelum memanggil setSummary()apa pun yang sesuai dengan aplikasi Anda.

gicci
sumber
1

Karena saya menggunakan kustom PreferenceDataStore, saya tidak bisa menambahkan pendengar ke beberapa SharedPreferencejadi saya harus menulis solusi yang agak aneh yang mendengarkan setiap preferensi:

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
sumber
1

Jika Anda menggunakan AndroidX Anda dapat menggunakan kustomSummaryProvider . Pendekatan ini bisa digunakan untuk apa saja Preference.

Contoh dari dokumentasi (Jawa):

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

Contoh dari dokumentasi (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
sumber