如何在"首选项"摘要中显示Android首选项的当前值?

nye*_*yec 450 user-interface android android-preferences

这必须经常出现.

当用户在Android应用中编辑首选项时,我希望他们能够在Preference摘要中查看首选项的当前设置值.

示例:如果我有"丢弃旧邮件"的"首选项"设置,该设置指定需要清除邮件的天数.在PreferenceActivity我想让用户看到:

"丢弃旧邮件" < - 标题

" x天后清理消息" < - summary其中x是当前的Preference值

额外的功劳:使这个可重用,所以我可以轻松地将它应用到我的所有首选项,无论其类型如何(这样它可以使用EditTextPreference,ListPreference等,只需最少的编码).

Doz*_*ows 151

如果符合您的需求,有很多方法可以使这个解决方案成为更通用的解决方案.

例如,如果您希望通常将所有列表首选项显示为摘要,则可以将其用于onSharedPreferenceChanged实现:

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

    if (pref instanceof ListPreference) {
        ListPreference listPref = (ListPreference) pref;
        pref.setSummary(listPref.getEntry());
    }
}
Run Code Online (Sandbox Code Playgroud)

这很容易扩展到其他偏好类.

并通过getPreferenceCountgetPreference在功能PreferenceScreenPreferenceCategory,你可以很容易地编写一个通用函数走偏好树设置类型的所有喜好的你渴望自己的概要toString表示

  • @ njzk2你所要做的就是确保活动`实现OnSharedPreferenceChangeListener` (8认同)
  • 好的解决方案确实 只缺少初始化 (6认同)
  • 注意:有一种更简单的方法,请参阅[@Robertas的回答](http://stackoverflow.com/questions/531427/how-do-i-display-the-current-value-of-an-android-preference-in -the偏好苏#9938201). (4认同)
  • 实际上,你可以为`ListPreference`设置汇总为"%s"`,`ListPreference.getSummary()`将使用当前选中的条目格式化汇总(如果没有选择,则为`""`). (4认同)

Edd*_*ieB 142

这是我的解决方案...... 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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Rob*_*tas 92

Android 文档说可以在以下位置使用String格式标记getSummary():

如果摘要中包含字符串格式标记(即"%s"或"%1 $ s"),则当前条目值将替换为其位置.

只需android:summary="Clean up messages after %s days"在ListPreference中指定xml声明就适合我.

注意:这仅适用于ListPreference.

  • 不幸的是,这仅适用于ListPreference.我想要EditTextPreference的相同行为.令人惊讶的是,Google没有为所有DialogPreferences添加此功能. (9认同)
  • 这很好,但不适用于较旧的API. (3认同)
  • @Zordid可以通过在ListPreference中指定xml中的默认值来修复,例如`android:defaultValue ="0"`.这是最明智的答案,对我有用. (3认同)
  • 另外,只要没有设置值,我就无法工作 - 在第一次调用Preference活动时,它只显示%s,这真的很愚蠢. (2认同)

tde*_*aux 81

如果你使用PreferenceFragment,这就是我解决它的方式.这是自我解释的.

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"));
    }
  }
Run Code Online (Sandbox Code Playgroud)

  • 你在哪里调用`unregisterOnSharedPreferenceChangeListener`? (6认同)
  • 这个解决方案需要更多的投票...这让我觉得开发人员网站上的示例显示了这一点,但完全省略了它. (3认同)
  • 为了使EditTextPreferences也更新,将其添加到`updatePreference` CODE`if(preference instanceof EditTextPreference){EditTextPreference editTextPref =(EditTextPreference)preference; preference.setSummary(editTextPref.getText()); 谢谢@EddieB (3认同)
  • @ DSlomer64我很清楚你在引用什么.它告诉你不要使用'PreferenceActivity.findPreference`(以及其他几种方法),因为谷歌希望你切换到这个答案中显示的技术,它使用的是'PreferenceFragment.findPreference`. (2认同)

You*_*ave 32

我的选择是扩展ListPreference并且它是干净的:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后添加settings.xml:

<yourpackage.ListPreferenceShowSummary
    android:key="key" android:title="title"
    android:entries="@array/entries" android:entryValues="@array/values"
    android:defaultValue="first value"/>
Run Code Online (Sandbox Code Playgroud)

  • 似乎比最高票的解决方案更容易和更清洁! (4认同)
  • 当用户更改该首选项时,`init()` 函数对于更新 `summary` 是必要的。没有它,它只会保留最初的条目。 (2认同)

Pal*_*ani 23

您可以覆盖默认的Preference类并实现该功能.

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的xml中,您可以使用自定义首选项

<your.package.name.MyListPreference 
    android:key="noteInterval"
    android:defaultValue="60"
    android:title="Notification Interval"
    android:entries="@array/noteInterval"
    android:entryValues="@array/noteIntervalValues"
    />
Run Code Online (Sandbox Code Playgroud)


Sub*_*Fox 21

几个小时后,我已经花了解决这个问题,我已经实现了这段代码:

[更新:最终版本列表]

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是唯一对我有用的解决方案.在我尝试从ListPreferences继承并实现android:summary ="bla bla bla%s"之前.都没有奏效.


Eru*_*nos 19

也许像ListPreference:修改getSummary以获得你想要的:

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());
        }
    }
Run Code Online (Sandbox Code Playgroud)

并在你的xml中使用它:

<your.package.EditTextPreference
                android:key="pref_alpha"
                android:summary="Actual value: %s"
                android:title="Title"
                android:defaultValue="default"
                />
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用%s而不是实际值来编写摘要.


小智 18

这是将摘要设置为所选值所需的代码.它还会在启动时设置值并遵循默认值,而不仅仅是更改时.只需将"R.layout.prefs"更改为您的xml文件,并将setSummary-method扩展到您的需要.它实际上只处理ListPreferences,但它很容易自定义以尊重其他首选项.

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";
}
Run Code Online (Sandbox Code Playgroud)

koem

  • 顺便说一句:请注意,使用此系统不会更新非持久性首选项.必须使用各个首选项的`setOnPreferenceChangeListener(Preference.OnPreferenceChangeListener onPreferenceChangeListener)`-method来监听对它们的更改. (2认同)

dha*_*g23 11

实际上,CheckBoxPreference确实能够根据复选框值指定不同的摘要.查看android:summaryOff和android:summaryOn属性(以及相应的CheckBoxPreference方法).


lor*_*max 11

对于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);
    }
}
Run Code Online (Sandbox Code Playgroud)


ali*_*hir 9

根据Android 文档,您可以app:useSimpleSummaryProvider="true"在 ListPreference 和 EditTextPreference 组件中使用。

  • 如果您使用“androidx.preference.EditTextPreference”,这实际上应该是公认的答案 (2认同)

小智 8

如果有人仍在寻找答案,你应该查看三十三分之一的答案.

<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" />
Run Code Online (Sandbox Code Playgroud)

Android将使用首选项的当前字符串值替换%s,如ListPreference的选择器所示.


ale*_*exx 7

谢谢你的提示!

我有一个首选项屏幕,并希望显示每个列表首选项的值作为摘要.

这是我现在的方式:

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

这对我有用,但我想知道什么是最好的解决方案(性能,稳定性,可扩展性):一个Koem正在展示还是这个?


Chr*_*ris 6

谢谢,Reto,详细解释!

如果这对任何人有任何帮助,我不得不更改Reto Meier提出的代码,以使其适用于Android版SDK 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            
    ...
}
Run Code Online (Sandbox Code Playgroud)

相同的更改适用于回调函数 onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)

干杯,

克里斯


Chr*_*cía 5

我已经看到所有投票的答案都显示了如何使用确切的当前值设置摘要,但 OP 还想要以下内容:

x天后清理消息”* <- 摘要,其中x是当前首选项值

这是我实现这一目标的答案

按照该文件ListPreference.getSummary()

返回此 ListPreference 的摘要。如果摘要中有字符串格式标记(即“%s”或“%1$s”),则当前条目值将被替换。

但是,我在多个设备上尝试了此方法,但似乎不起作用。通过一些研究,我在这个答案中找到了一个很好的解决方案。它只包括扩展Preference您使用的所有内容并覆盖getSummary()以按照 Android 文档的规定工作。


小智 5

在 Android Studio 中,打开“root_preferences.xml”,选择设计模式。选择所需的 EditTextPreference 首选项,然后在“所有属性”下查找“useSimpleSummaryProvider”属性并将其设置为 true。然后它将显示当前值。