これは頻繁に起こります。
ユーザーがAndroidアプリで設定を編集しているときは、Preference
サマリーで現在設定されている設定の値を確認できるようにしたいと思います。
例:「古いメッセージを破棄する」の設定で、メッセージをクリーンアップするまでの日数を指定したとします。 PreferenceActivity
では、ユーザーに見てもらいたいのですが。
"古いメッセージを破棄する"< - title
"x日後にメッセージを整理する"< - summary wherexは現在の設定値です。
余計なことに:これを再利用可能にすることで、タイプに関係なく自分のすべての設定に簡単に適用できるようになります(それにより、最小限のコーディングでEditTextPreference、ListPreferenceなどで機能します)。
これがあなたのニーズに合っていれば、これをより一般的な解決策にする方法があります。
たとえば、すべてのリスト設定に概要としての選択を表示させる場合は、onSharedPreferenceChanged
の実装にこれを含めることができます。
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference pref = findPreference(key);
if (pref instanceof ListPreference) {
ListPreference listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry());
}
}
これは他の設定クラスにも簡単に拡張できます。
そしてgetPreferenceCount
およびgetPreference
でPreferenceScreen
およびPreferenceCategory
機能を使用することによって、好みの型のすべての設定の要約をそれらのtoString
表現に設定する設定ツリーをたどるための一般的な関数を簡単に書くことができます。
これが私の解決策です... 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());
}
}
}
Android ドキュメント はgetSummary()
で文字列フォーマットマーカーを使うことができると言っています:
サマリーに文字列フォーマットマーカー( "%s"または "%1 $ s")がある場合は、現在のエントリ値が代わりに使用されます。
ListPreference xml宣言でAndroid:summary="Clean up messages after %s days"
を指定するだけでうまくいきました。
注:これはListPreference
に対してのみ機能します。
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"));
}
}
私の選択は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();
}
}
次にsettings.xmlに追加します。
<yourpackage.ListPreferenceShowSummary
Android:key="key" Android:title="title"
Android:entries="@array/entries" Android:entryValues="@array/values"
Android:defaultValue="first value"/>
デフォルトの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());
}
}
後であなたのxmlあなたはのようなカスタム設定を使うことができます
<your.package.name.MyListPreference
Android:key="noteInterval"
Android:defaultValue="60"
Android:title="Notification Interval"
Android:entries="@array/noteInterval"
Android:entryValues="@array/noteIntervalValues"
/>
数時間後、このような問題を解決するために私はこのコードを実装しました:
[更新:最終版のリスト]
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);
}
}
それが私にとってうまくいった唯一の解決策でした。 ListPreferencesからサブクラス化してAndroidを実装しようとする前に:summary = "bla bla bla%s"。どちらもうまくいきませんでした。
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());
}
}
そしてあなたのxmlの中でこれを使ってください:
<your.package.EditTextPreference
Android:key="pref_alpha"
Android:summary="Actual value: %s"
Android:title="Title"
Android:defaultValue="default"
/>
ですから、実際の値の代わりに%s
を使って要約を書くことができます。
これは、要約を選択した値に設定するために必要なコードです。また、起動時に値を設定し、変更時だけでなくデフォルト値も考慮します。 "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";
}
コエム
実際、 CheckBoxPreference にはチェックボックスの値に基づいて異なる要約を指定する機能があります。 Android:summaryOff属性とAndroid:summaryOn属性(および対応するCheckBoxPreferenceメソッド)を参照してください。
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);
}
}
誰かがまだこれに対する答えを探しているならば、あなたは thirtyforty sの答えをチェックするべきです。
<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" />
ListPreferenceのピッカーによって表示されるように、Androidは%sを現在の設定の文字列値に置き換えます。
このヒントをありがとう!
私は一つの設定画面があり、それぞれのリスト設定の値を要約として表示したいと思います。
これは今私の道です:
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());
}
}
これは私にとってはうまくいきますが、最良の解決策(パフォーマンス、安定性、スケーラビリティ)は何なのかと疑問に思います。
詳しい説明をありがとうございます。
これがだれにとっても助けになる場合は、Reto Meierによって提案されたコードを変更して、SDK for 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
...
}
コールバック関数onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
にも同じ変更が適用されます。
乾杯、
クリス
私はすべての投票された答えが正確な現在の値で要約を設定する方法を示すのを見ました、しかしOPはまたそのようなものを望んでいました:
"x日後のメッセージを整理する" * < - まとめここでx現在の設定値です。
これを達成するための私の答えは次のとおりです
As documentation はListPreference.getSummary()
について述べています。
このListPreferenceの概要を返します。サマリーに文字列フォーマットマーカー( "%s"または "%1 $ s")がある場合は、現在のエントリ値が代わりに使用されます。
しかし、私はいくつかのデバイスを試してみましたが、うまくいかないようです。いくつかの調査で、私は この答え で良い解決策を見つけました。それは単にあなたが使うすべてのPreference
を拡張し、Androidのドキュメントによって指定されたように動作するようにgetSummary()
をオーバーライドすることから成ります。
私は次のListPreferenceの子孫で問題を解決しました:
public class EnumPreference extends ListPreference {
public EnumPreference(Context aContext, AttributeSet attrs) {
super(aContext,attrs);
}
@Override
protected View onCreateView(ViewGroup parent) {
setSummary(getEntry());
return super.onCreateView(parent);
}
@Override
protected boolean persistString(String aNewValue) {
if (super.persistString(aNewValue)) {
setSummary(getEntry());
notifyChanged();
return true;
} else {
return false;
}
}
}
1.6から4.0.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;
}
}
これが私の解決策です:
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";
}
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()");
}
PreferenceActivityと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();
}
単に:
listPreference.setSummary("%s");
要約として各フィールドのプレーンテキスト値のみを表示する場合は、次のコードを維持するのが最も簡単なはずです。 2つの変更のみが必要です(13行目と21行目、 "change here"とマークされています)。
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);
}
}
参考:
findPreference(CharSequence key)
This method was deprecated in API level 11. This function is not relevant
for a modern fragment-based PreferenceActivity.
%s
の各フィールドにAndroid:summary
のpreferences.xml
を使用すると言っている、上記の@ASDの非常に滑らかなAnswer
( ソースはここにあります )を見るさらに多くの理由。 (現在の設定値は%s
に置き換えられます。)
<ListPreference
...
Android:summary="Length of longest Word to return as match is %s"
...
/>
EditTextPreferenceの場合:
あなたが特定のedittextpreferenceを必要としているけれども、あなたがあらゆるPreferenceでこれをすることができるならば、もちろん、私はこの解決策に来ました:
............
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, ""));
}
}
次に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);
}
に:
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
updatePreference(findPreference(key), key);
}
ここでは、これらすべてがEclipseサンプルSettingsActivity
から切り取られています。私はこれらのAndroid開発者がより一般化された安定したコーディングスタイルのためにどのように完璧に選択するかを示すためにこれらのあまりにも多くのコードをコピーしなければなりません。
私はPreferenceActivity
をタブレットとより優れたAPIに適応させるためのコードを残しました。
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>
注:実際には、 "GoogleのPreferenceActivityのサンプルも興味深い"のようにコメントしたいだけです。評判ポイントが足りません。私を責めないでください。
(悪い英語でごめんね)
OnCreateメソッドでbindPreferenceSummaryToValue関数を使用する必要があります。
例:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add 'general' preferences, defined in the XML file
addPreferencesFromResource(R.xml.pref_general);
// For all preferences, attach an OnPreferenceChangeListener so the UI summary can be
// updated when the preference changes.
bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_units_key)));
}
Udacity Androidコースのレッスン3を参照してください。 https://www.udacity.com/course/viewer#!/c-ud853/l-1474559101/e-1643578599/m-1643578601
私の解決策は、次のようにXMLで使用されるカスタムのEditTextPreference
を作成することです。<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();
}
}
Androidx Preferenceクラスには SummaryProvider インターフェースがあるので、OnSharedPreferenceChangeListenerを使わなくても実行できます。単純な実装は、EditTextPreferenceとListPreferenceに提供されています。上に構築 EddieBの答え それはこのように見えることができます。 androidx.preferenceでテスト済み:preference: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());
}
}
}
私はカスタムのPreferenceDataStore
を使用しているので、いくつかのSharedPreference
にリスナーを追加することはできません。そのため、それぞれの設定に耳を傾けるややハックな解決策を書く必要がありました。
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)
}
ダイアログで選択された値にListPreference
の概要を設定するために、あなたはこのコードを使うことができました:
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());
}
}
そして、yourpackage.ListPreference
内のpreferences.xml
オブジェクトを参照して、Android:defaultValue
をそこに指定することを忘れないでください。これにより、onSetInitialValue()
の呼び出しがトリガーされます。
必要に応じて、setSummary()
を呼び出す前にテキストを変更して、アプリケーションに適したものにすることができます。
Android docs によると、ListPreferenceおよびEditTextPreferenceコンポーネントでapp:useSimpleSummaryProvider="true"
を使用できます。
AndroidXを使用している場合は、 カスタムSummaryProvider
を使用 が可能です。このアプローチはどのPreference
にも使用できます。
ドキュメントからの例(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();
}
});
ドキュメントの例(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
}
}
サポートライブラリのEditTextPreference
を"%s"
にまとめて(ListPreference
がすでに処理しているので)作成する方法を見つけました。
public class EditTextPreference extends Android.support.v7.preference.EditTextPreference {
public EditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void setText(String text) {
super.setText(text);
notifyChanged();
}
@Override
public CharSequence getSummary() {
String text = super.getText();
String summary = super.getSummary().toString();
return String.format(summary, text == null ? "" : text);
}
}
XMLでは、このようになります。
<com.example.yourapp.EditTextPreference
Android:defaultValue="1"
Android:key="cleanup_period"
Android:summary="Clean up messages after %s days"
Android:title="Clean up period" />
これは、@ tdeveaux回答に基づいた、EditTextPreference
内のすべてのPreferenceFragment
に対する実用的な解決策です。
public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "SettingsFragment";
@Override
public void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onResume () {
super.onResume();
for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); ++i) {
Preference preference = getPreferenceScreen().getPreference(i);
updatePreference(preference);
}
}
@Override
public void onSharedPreferenceChanged (SharedPreferences sharedPreferences, String key) {
updatePreference(findPreference(key));
}
private void updatePreference (Preference preference) {
if (preference instanceof EditTextPreference) {
EditTextPreference editTextPreference = (EditTextPreference)preference;
editTextPreference.setSummary(editTextPreference.getText());
}
}
}