Làm cách nào để hiển thị giá trị hiện tại của Tùy chọn Android trong tóm tắt Tùy chọn?


457

Điều này phải đến rất thường xuyên.

Khi người dùng đang chỉnh sửa tùy chọn trong ứng dụng Android, tôi muốn họ có thể thấy giá trị hiện được đặt của tùy chọn trong Preferencebản tóm tắt.

Ví dụ: nếu tôi có cài đặt Tùy chọn cho "Hủy tin nhắn cũ" chỉ định số ngày sau đó tin nhắn cần được xóa. Trong phần PreferenceActivityTôi muốn người dùng thấy:

"Hủy tin nhắn cũ" <- title

"Dọn dẹp tin nhắn sau x ngày" <- tóm tắt trong đó x là giá trị Tùy chọn hiện tại

Tín dụng bổ sung: làm cho nó có thể tái sử dụng, vì vậy tôi có thể dễ dàng áp dụng nó cho tất cả các tùy chọn của mình bất kể loại của chúng (để nó hoạt động với EditTextPreference, ListPreference, v.v. với số lượng mã hóa tối thiểu).

Câu trả lời:


151

Có nhiều cách để biến điều này thành một giải pháp chung chung hơn, nếu phù hợp với nhu cầu của bạn.

Ví dụ: nếu bạn muốn tổng quát tất cả các tùy chọn danh sách hiển thị lựa chọn của họ dưới dạng tóm tắt, bạn có thể có điều này để onSharedPreferenceChangedthực hiện:

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

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

Điều này dễ dàng mở rộng cho các lớp ưu tiên khác.

Và bằng cách sử dụng getPreferenceCountgetPreferencechức năng trong PreferenceScreenPreferenceCategory, bạn có thể dễ dàng viết một hàm chung để đi bộ cây ưu tiên thiết lập các bản tóm tắt của tất cả các tùy chọn của loại bạn muốn toStringđại diện cho chúng


6
giải pháp tốt đẹp thực sự. chỉ thiếu một khởi tạo
njzk2

9
@ njzk2 tất cả những gì bạn phải làm là đảm bảo hoạt độngimplements OnSharedPreferenceChangeListener

4
NB: Có một cách đơn giản hơn, xem câu trả lời của @ Robertas .
Salman von Abbas

6
Trên thực tế, bạn có thể đặt tóm tắt thành "%s"cho ListPreferenceListPreference.getSummary()sẽ định dạng tóm tắt với mục được chọn hiện tại (hoặc ""nếu không được chọn).
SOFe

findPreference (khóa) không được dùng nữa, có cách nào khác để truy cập cái này không?
Không bao giờ

144

Đây là giải pháp của tôi ... 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());
        }
    }
}

Điều này hoạt động rất tốt @EddieB ... ngoại trừ việc tôi có màn hình ưu tiên trong màn hình tùy chọn. Bất kỳ ý tưởng làm thế nào để đạt được màn hình ưu tiên bên trong và điền vào những người có tóm tắt?
taraloca

@taraloca - thay đổi if (p instanceof PreferenceC Category) {PreferenceC Category pCat = (PreferenceC Category) p; to if (p instanceof Preferencegroup) {Final Preferencegroup pCat = (Preferencegroup) p;
Martin dila

vĩ đại này đang làm việc gì nếu EditTextPreferenceandroid:password="true" nó cho thấy giá trị
Chathura Wijesinghe

1
Tôi nên sửa đổi mã như thế nào để hiển thị tóm tắt từ tệp tài nguyên (xml) nếu không có giá trị nào được xác định (nghĩa là if editTextPref.getText() == "")? Làm thế nào để có được giá trị tóm tắt tại updatePrefSummary? p.getSummary()editTextPref.getSummary()trả về các giá trị đã được sửa đổi.
LA_

Vì cả hai PreferenceCategoryPreferenceScreenthừa kế từ PreferenceGroup, tôi đã thay đổi initSummaryđể xử lý PreferenceGroupthay thế. Điều này tránh sự cần thiết của một vòng lặp khác trong onCreate(). Thay đổi hành vi: PreferenceScreen lồng nhau bây giờ cũng được xử lý đệ quy.
Lekensteyn

96

Tài liệu Android cho biết người ta có thể sử dụng dấu định dạng Chuỗi trong getSummary():

Nếu tóm tắt có dấu định dạng Chuỗi trong đó (nghĩa là "% s" hoặc "% 1 $ s"), thì giá trị mục nhập hiện tại sẽ được thay thế ở vị trí của nó.

Chỉ cần chỉ định android:summary="Clean up messages after %s days"trong khai báo Listmlreference xml làm việc cho tôi.

Lưu ý: Điều này chỉ hoạt động cho ListPreference.


Ai đó sửa tôi nếu tôi sai, nhưng tài liệu về getSummary () nói rằng nó đã được thêm vào API cấp 1. Bạn có ngụ ý rằng hành vi đó khác khi phát hành lần đầu không?
TheIT 19/12/13

10
Thật không may, điều này chỉ hoạt động cho ListPreference. Tôi muốn hành vi tương tự cho EditTextPreference. Thật đáng ngạc nhiên khi Google đã không thêm điều này cho tất cả các DialogPreferences.
Vicki

2
Thêm vào đó, tôi không hoạt động miễn là giá trị chưa được đặt - trong lần gọi đầu tiên của hoạt động Ưu tiên, nó chỉ hiển thị% s thực sự bị câm.
Zordid

3
@Zordid Điều đó có thể được sửa bằng cách chỉ định giá trị mặc định trong xml của bạn như android:defaultValue="0"trong ListPreference của bạn. Đây là câu trả lời hợp lý nhất và làm việc cho tôi.
Mohit Singh

@Mohit Singh / @Zordid, trên Lollipop API 22, defaultValue%skhông hoạt động. Trên các phiên bản khác, nói chung, nó hoạt động mặc dù. Giải pháp nào vui lòng? Tôi chắc chắn không muốn viết một lớp tùy chỉnh cho việc này. Không thể tin được rằng Google lại biến những nhiệm vụ tầm thường nhất thành một nỗi đau như vậy.
Narayana J

81

Nếu bạn sử dụng PreferenceFragment, đây là cách tôi giải quyết nó. Đó là tự giải thích.

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
Giải pháp này cần nhiều phiếu hơn ... Điều đó làm tôi bực mình vì các ví dụ trên trang web của nhà phát triển HIỂN THỊ điều này đã được thực hiện, nhưng bỏ qua nó hoàn toàn.
Justin Smith

3
Để có được EditTextPreferences cũng được cập nhật, hãy thêm phần này vào updatePreferenceCODE, if (preference instanceof EditTextPreference) { EditTextPreference editTextPref = (EditTextPreference) preference; preference.setSummary(editTextPref.getText()); }cảm ơn @EddieB
Eugene van der Merwe

6
Bạn gọi ở unregisterOnSharedPreferenceChangeListenerđâu
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 Tôi biết rõ những gì bạn đang trích dẫn. Điều đó nói với bạn rằng không nên sử dụng PreferenceActivity.findPreference(và một số phương pháp khác), bởi vì Google muốn bạn chuyển sang kỹ thuật được hiển thị trong câu trả lời này, sử dụng PreferenceFragment.findPreferencethay thế.
Dan Hulme

33

Tùy chọn của tôi là mở rộng ListPreference và nó sạch sẽ:

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

Sau đó, bạn thêm vào tệp cài đặt của mình:

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

Tôi đã thực hiện một giải pháp dựa trên điều này. Trong giải pháp của tôi, tôi có một phương pháp để thiết lập một mảng entrySummaries thay vì sử dụng các chuỗi mục trong cả menu và tóm tắt. Có một vấn đề ở đây: getEntry () trả về giá trị trước đó chứ không phải giá trị mới.
pzulw

1
Trên thực tế là init () thậm chí không cần thiết? Tôi vừa mới vượt qua getSummary () và nó dường như hoạt động hoàn hảo!
Andy

4
Có vẻ là một giải pháp dễ dàng và sạch sẽ hơn nhiều so với giải pháp được bình chọn cao nhất!
muslidrikk

2
Các init()chức năng là cần thiết để cập nhật summarykhi người dùng thay đổi sở thích đó. Không có nó, nó sẽ chỉ ở lại bất cứ mục nào ban đầu.
anthonylawson

23

Bạn có thể ghi đè các lớp Tùy chọn mặc định và triển khai tính năng này.

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

Sau này trong xml bạn có thể sử dụng tùy chọn tùy chỉnh như

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

Phương pháp đơn giản tuyệt vời. Chỉ cần coi chừng những thứ như% trong chuỗi getEntry vì chúng có thể gây ra sự cố (hoặc chúng đã làm cho tôi)
Andrew

21

Sau vài giờ tôi đã dành để giải quyết vấn đề như vậy Tôi đã triển khai mã này:

[CẬP NHẬT: danh sách phiên bản cuối cùng]

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

Đó là giải pháp duy nhất hiệu quả với tôi. Trước đây tôi đã cố gắng phân lớp từ ListPreferences và triển khai android: Tóm tắt = "bla bla bla% s". Không làm việc.


Cách của bạn rõ ràng hơn và sử dụng ít mã hơn những người khác. Các câu trả lời hàng đầu hoạt động bằng cách sử dụng "proxy" - trình quản lý tùy chọn. Nó không rõ ràng như lắng nghe những thay đổi trực tiếp trong danh sách.
Paul Annekov

@Subussy Fox, giải pháp gọn gàng. chỉ tò mò nếu bạn đã làm 'setDefaultValue ()' thì tại sao phải kiểm tra (ss == null)
Samuel

Bởi vì setDefaultValue () không nên ở đó :) Tôi đã đặt mã này trước khi tái cấu trúc
Tinh tế Fox

20

Có thể như ListPreference: Sửa đổi getSummary để có được những gì bạn muốn:

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

Và sử dụng điều này trong xml của bạn:

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

Vì vậy, bạn có thể viết một bản tóm tắt với %sthay vì giá trị thực tế.


1
@Eruvanos @ serv-inc Ít nhất với một lớp con của android.support.v7.preference.EditTextPreference, điều này không cập nhật tóm tắt khi thay đổi tùy chọn, chỉ khi hoạt động tùy chọn được tạo. Một cách để giải quyết vấn đề này mà không thực hiện OnSharedPreferenceChangeListener.onSharedPreferenceChangedtrong lớp phân đoạn ưu tiên là ghi đè android.support.v7.preference.EditTextPreference.setText(String text):@Override public void setText(String text) { super.setText(text); this.setSummary(this.getText()); }
PointedEars

@PointedEars: đã xong. Nhưng đây dường như cũng là một bản sao của stackoverflow.com/a/21906829/1587329
serv-inc

18

Đây là mã bạn cần để đặt tóm tắt thành giá trị được chọn. Nó cũng đặt các giá trị khi khởi động và tôn trọng các giá trị mặc định, không chỉ thay đổi. Chỉ cần thay đổi "R.layout.prefs" thành tệp xml của bạn và mở rộng phương thức setSummary theo nhu cầu của bạn. Nó thực sự chỉ xử lý ListPreferences, nhưng nó dễ dàng tùy chỉnh để tôn trọng các Tùy chọn khác.

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

con gấu


Cảm ơn rất nhiều! Tôi đã tạo một lớp từ cái này, đưa id tài nguyên làm đối số cho onCreate () - theo cách đó, đó là một thay đổi một dòng cho màn hình cài đặt của tôi để chúng hiển thị các giá trị tóm tắt.
Asmo Soinio

2
BTW: Lưu ý rằng các tùy chọn không liên tục sẽ không được cập nhật bằng hệ thống này. Các thay đổi đối với chúng phải được lắng nghe bằng cách sử dụng setOnPreferenceChangeListener(Preference.OnPreferenceChangeListener onPreferenceChangeListener)-method của từng Sở thích riêng lẻ.
Asmo Soinio

11

Trên thực tế, CheckBoxPreference có khả năng chỉ định một bản tóm tắt khác nhau dựa trên giá trị hộp kiểm. Xem các thuộc tính android: Tóm tắt và android: Tóm tắt (cũng như các phương thức CheckBoxPreference tương ứng).


11

Đối với 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);
    }
}

9

Nếu ai đó vẫn đang tìm kiếm câu trả lời cho điều này, bạn nên kiểm tra câu trả lời thứ ba mươi .

<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ẽ thay thế% s bằng giá trị chuỗi hiện tại của tùy chọn, như được hiển thị bởi trình chọn của ListPreference.


Làm. Đây là giải pháp dễ nhất và tốt nhất hiện nay.
davidgyoung

1
Lưu ý rằng "% s" có thể được đặt ở bất cứ đâu trong chuỗi tóm tắt của bạn. Và vâng, bao gồm các chuỗi tài nguyên!
Scott Bigss

7

Cảm ơn vì mẹo này!

Tôi có một màn hình tùy chọn và muốn hiển thị giá trị cho từng tùy chọn danh sách dưới dạng tóm tắt.

Đây là cách của tôi bây giờ:

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

Điều này hiệu quả với tôi, nhưng tôi tự hỏi đâu là giải pháp tốt nhất (hiệu suất, tính ổn định, khả năng mở rộng): cái mà Koem đang hiển thị hay cái này là gì?


6

Cảm ơn, Reto, đã giải thích chi tiết!

Trong trường hợp điều này có ích với bất kỳ ai, tôi đã phải thay đổi mã do Reto Meier đề xuất để làm cho nó hoạt động với SDK cho 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            
    ...
}

Thay đổi tương tự áp dụng cho chức năng gọi lại onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)

Chúc mừng

Chris


4

Tôi đã giải quyết vấn đề với hậu duệ của ListPreference sau đây:

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

Có vẻ hoạt động tốt đối với tôi trong 1.6 đến 4.0.4.


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

Tôi đã thấy tất cả các câu trả lời được bình chọn cho thấy cách đặt tóm tắt với giá trị hiện tại chính xác, nhưng OP cũng muốn một cái gì đó như:

"Dọn dẹp tin nhắn sau x ngày" * <- tóm tắt trong đó x là giá trị Tùy chọn hiện tại

Đây là câu trả lời của tôi để đạt được điều đó

Như tài liệu nói về ListPreference.getSummary():

Trả về bản tóm tắt của ListPreference này. Nếu tóm tắt có dấu định dạng Chuỗi trong đó (nghĩa là "% s" hoặc "% 1 $ s"), thì giá trị mục nhập hiện tại sẽ được thay thế ở vị trí của nó.

Tuy nhiên, tôi đã thử trên một số thiết bị và nó dường như không hoạt động. Với một số nghiên cứu, tôi tìm thấy một giải pháp tốt trong câu trả lời này . Nó đơn giản chỉ bao gồm việc mở rộng mọi thứ Preferencebạn sử dụng và ghi đè getSummary()để hoạt động theo quy định của tài liệu Android.


1
Nó dường như hoạt động ban đầu, nhưng khi bạn chọn một giá trị mới, nó sẽ không tự động cập nhật cho đến khi bạn làm gì đó để vô hiệu hóa toàn bộ hoạt động và khiến nó vẽ lại. Tôi đang dùng Android 4.0.4.
eidylon

Sẽ thật tuyệt nếu Google có thể thêm một chuỗi định dạng vào đối tượng ưu tiên.
Justin Smith

3

Nếu bạn chỉ muốn hiển thị giá trị văn bản đơn giản của từng trường dưới dạng tóm tắt của nó, mã sau đây sẽ dễ duy trì nhất. Nó chỉ yêu cầu hai thay đổi (dòng 13 và 21, được đánh dấu bằng "thay đổi tại đây"):

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

Đây là giải pháp của tôi:

Xây dựng phương thức 'getter' ưu tiên.

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

Xây dựng phương thức '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()");
    }

Khởi tạo

Tạo lớp công khai PreferenceActivity và thực hiện 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();
}


3

Tài chính

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

Tất cả các lý do hơn để nhìn vào trơn rất Answercủa @ASD trên ( nguồn tìm thấy ở đây ) nói để sử dụng %strong android:summarytừng lĩnh vực trong preferences.xml. (Giá trị hiện tại của ưu tiên được thay thế cho %s.)

nhập mô tả hình ảnh ở đây

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

3

Vì trong lớp Prex của androidx có giao diện SummaryProvider , nên nó có thể được thực hiện mà không cần OnSharedPreferenceChangeListener. Việc triển khai đơn giản được cung cấp cho EditTextPreference và ListPreference. Dựa trên câu trả lời của EddieB, nó có thể trông như thế này. Đã thử nghiệm trên androidx.preference: ưu tiên: 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());
        }
    }
}


2

Ở đây, tất cả những thứ này được cắt từ mẫu Eclipse SettingsActivity . Tôi phải sao chép tất cả các mã này quá nhiều để chỉ ra cách các nhà phát triển Android chọn hoàn hảo cho phong cách mã hóa tổng quát và ổn định hơn.

Tôi đã để lại mã để điều chỉnh PreferenceActivitymáy tính bảng và API lớn hơn.

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>

LƯU Ý: Thật ra tôi chỉ muốn bình luận như "mẫu của Google cho PreferenceActivity cũng thú vị". Nhưng tôi không đủ điểm danh tiếng. Làm ơn đừng đổ lỗi cho tôi.

(Xin lỗi về tiếng Anh kém)


2

Bạn phải sử dụng hàm bindPreferenceSummaryToValue trên phương thức onCreate.

Thí dụ:

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

Xem bài 3 về Khóa học Android Udacity: https://www.udacity.com/cference/viewer#!/c-ud853/l-1474559101/e-1643578599/m-1643578601


2

Đối với EditTextPreference :

Tôi đã đến với giải pháp này, tất nhiên, chỉ khi bạn cần edittextpreference cụ thể nhưng bạn có thể làm điều này với mọi Ưu tiên:

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

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

            }
}

Sau đó, trong 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);
        }

Trong:

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

2

Giải pháp của tôi là tạo một tùy chỉnh EditTextPreference, được sử dụng trong XML như thế này:<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

Để đặt tóm tắt của a ListPreferencethành giá trị được chọn trong hộp thoại, bạn có thể sử dụng mã này:

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

và tham chiếu yourpackage.ListPreferenceđối tượng mà bạn preferences.xmlnhớ để chỉ định ở đó android:defaultValuevì điều này sẽ kích hoạt lệnh gọi đến onSetInitialValue().

Nếu bạn muốn, sau đó bạn có thể sửa đổi văn bản trước khi gọi setSummary()bất cứ điều gì phù hợp với ứng dụng của bạn.


1

Vì tôi đang sử dụng một tùy chỉnh PreferenceDataStore, tôi không thể thêm người nghe vào một số SharedPreferencevì vậy tôi đã phải viết một giải pháp hơi khó nghe theo từng sở thích:

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

Nếu bạn đang sử dụng AndroidX, bạn có thể sử dụng một tùy chỉnhSummaryProvider . Cách tiếp cận này có thể được sử dụng cho bất kỳPreference .

Ví dụ từ tài liệu (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();
    }
});

Ví dụ từ tài liệu (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
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.