簡體   English   中英

使用新值更改 ListPreference 的摘要 (Android)

[英]Change the summary of a ListPreference with the new value (Android)

如何將 ListPreference 的摘要修改為用戶選擇的新“條目”字符串(不是條目值)

我認為它與 setOnPreferenceChangeListener() 但在

new OnPreferenceChangeListener() {

        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            return true;
        }
    }

使用 ((ListPreference)preference).getEntry() 我得到舊值(因為它尚未更改)並且 newValue.toString() 返回條目值(不是顯示給用戶的條目文本)

我該怎么做? 提前致謝

只需在 xml 描述中將匯總值設置為%s即可。

編輯:我已經在幾台設備上對其進行了測試,但它並沒有真正起作用。 這很奇怪,因為根據文檔它必須工作: ListPreference.getSummary()

但是可以自己實現這個功能。 該實現需要從ListPreference class 繼承:

public class MyListPreference extends ListPreference {
    public MyListPreference(final Context context) {
        this(context, null);
    }

    public MyListPreference(final Context context, final AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public CharSequence getSummary() {
        final CharSequence entry = getEntry();
        final CharSequence summary = super.getSummary();
        if (summary == null || entry == null) {
             return null;
        } else {
            return String.format(summary.toString(), entry);
        }
    }

    @Override
    public void setValue(final String value) {
        super.setValue(value);
        notifyChanged();
    }
}

如您所見MyListPreference有自己的匯總字段,可以包含格式標記。 當首選項的值發生變化時,會調用Preference.notifyChanged()方法,並導致從Preference.onBindView()調用MyListPreference.getSummary()方法。

PS:此方法尚未經過充分測試,因此可能包含錯誤。

瑙曼祖拜爾是對的。

%s實現是錯誤的。 視圖在首次加載時顯示正確的值(如果設置了默認列表值),但在選擇列表項時視圖不會更新。 您必須切換復選框或其他一些偏好來更新視圖。

作為一種解決方法,實施OnSharedPreferenceChangeListener以覆蓋列表首選項的摘要。

/src/apps/app_settings/SettingsActivity.java

package apps.app_settings;

import android.os.Bundle;
import android.preference.PreferenceActivity;

public class SettingsActivity extends PreferenceActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        /* set fragment */
        getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
    }
}

/src/apps/app_settings/SettingsFragment.java

package apps.app_settings;

import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;

public class SettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        /* set preferences */
        addPreferencesFromResource(R.xml.preferences);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        /* get preference */
        Preference preference = findPreference(key);

        /* update summary */
        if (key.equals("list_0")) {
            preference.setSummary(((ListPreference) preference).getEntry());
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onPause() {
        getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
        super.onPause();
    }
}

/res/xml/preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
  xmlns:android="http://schemas.android.com/apk/res/android">
  <ListPreference
    android:key="list_0"
    android:title="@string/settings_list_0_title"
    android:summary="%s"
    android:entries="@array/settings_list_0_entries"
    android:entryValues="@array/settings_list_0_entry_values"
    android:defaultValue="@string/settings_list_0_default_value"/>
</PreferenceScreen>

/res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="settings_list_0_title">list 0</string>
  <string-array name="settings_list_0_entries">
    <item>item 0</item>
    <item>item 1</item>
    <item>item 2</item>
  </string-array>
  <string-array name="settings_list_0_entry_values">
    <item>0</item>
    <item>1</item>
    <item>2</item>
  </string-array>
  <string name="settings_list_0_default_value">0</string>
</resources>

我用另一個簡單的解決方案解決了這個問題(https://gist.github.com/brunomateus/5617025)

public class ListPreferenceWithSummary extends ListPreference{

public ListPreferenceWithSummary(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public ListPreferenceWithSummary(Context context) {
    super(context);
}

@Override
public void setValue(String value) {
    super.setValue(value);
    setSummary(value);
}

@Override
public void setSummary(CharSequence summary) {
    super.setSummary(getEntry());
}
}

這在我的 GirgerBeard 設備上運行良好。 即使是第一次運行您的應用程序。 不要忘記在您的 xml 偏好設置上提供默認值:

android:defaultValue="default value"

並在您的PreferenceActivityPrefenceFragment上設置默認值:

 PreferenceManager.setDefaultValues(this, R.xml.you pref file, false);

我建議在您的 PreferenceFragment 或 PreferenceActivity 中實現 OnSharedPreferenceChangeListener 而不是 Preference.setOnPreferenceChangeListner。 使用 setSummay 設置新的更改。 (不要忘記注冊和取消注冊監聽器。)在對首選項的更改完成后調用此監聽器。 您還應該在 XML 中為首選項設置默認值。

通過將 %s 直接寫入 XML 文件,“%s”解決方案適用於 android 4.0.3。 問題是在我更改了首選項的值后文本沒有更新,但是當我修改了我的 PreferenceScreen 的另一個首選項時。 也許這里缺少一些刷新。

這是我實現的最簡化的方式。 只需取 onPreferenceChange 監聽器給出的值

    ListPreference preference;        
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    preference = (ListPreference)findPreference("myKey");
    preference.setSummary(preferenceColorButtons.getEntry());
    preference.setOnPreferenceChangeListener(new        OnPreferenceChangeListener() {

        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            ListPreference listPreference = (ListPreference)preference;
            int id = 0;
            for (int i = 0; i < listPreference.getEntryValues().length; i++)
            {
                if(listPreference.getEntryValues()[i].equals(newValue.toString())){
                    id = i;
                    break;
                }
            }
            preference.setSummary(listPreference.getEntries()[id]);
            return true;
        }
    });

}

據我所知:

a) %s 確實適用於 android 4,但不適用於 2.x。

b)如果您在兩者之間設置一個虛擬值,則可以實現更新,請參見此處: https://stackoverflow.com/a/16397539/1854563

無需擴展 ListPreference 或遍歷 entryValues 等

public boolean onPreferenceChange(Preference preference, Object newValue) {
    int i = ((ListPreference)preference).findIndexOfValue(newValue.toString());
    CharSequence[] entries = ((ListPreference)preference).getEntries();
    preference.setSummary(entries[i]);

    return true;
}

我知道這是一個非常古老的問題,但它仍然是實際的。 要自動更新摘要,您必須調用原始的preferenceChangeListener:

final OnPreferenceChangeListener listener = preference.getOnPreferenceChangeListener();
preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
        {
            @Override
            public boolean onPreferenceChange(Preference preference, Object o)
            {
                if (listener !=null)
                    listener .onPreferenceChange(preference, o);

                return true;
            }
        });

我也遇到了這個問題,我終於通過使用來自偵聽器的值找到了解決方案。 在下面的示例中(對於 ListPreference),我首先獲取 ListPreference 數組中值的索引,然后使用該索引檢索該值的 label:

passwordFrequencyLP.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            int newFrequency = Integer.valueOf(newValue.toString());

            prefs.edit().putInt("settings_key_password_frequency", newFrequency).commit();

            //get the index of the new value selected in the ListPreference array
            int index = passwordFrequencyLP.findIndexOfValue(String.valueOf(newValue));
            //get the label of the new value selected
            String label = (String) passwordFrequencyLP.getEntries()[index];

            passwordFrequencyLP.setSummary(label);

            makeToast(getResources().getString(R.string.password_frequency_saved));
            return true;
        }
    });

這個小技巧效果很好,我找到了許多不同的可能解決方案,但只有這個對我有用。

如果有幫助,您好為 EditText 編輯了上述內容:)

package fr.bmigette.crocoschedulerconsoleandroid;
import android.content.Context;
import android.preference.EditTextPreference;
import android.util.AttributeSet;

/**
 * Created by bastien on 28/07/2015.
 */
public class EditTextPreferenceWithSummary extends EditTextPreference{
    public EditTextPreferenceWithSummary(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public EditTextPreferenceWithSummary(Context context) {
        super(context);
    }

    @Override
    public void setText(String value) {
        super.setText(value);
        setSummary(value);
    }

    @Override
    public void setSummary(CharSequence summary) {
        super.setSummary(getText());
    }
}

並像這樣創建preference.xml:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <PreferenceCategory
        android:key="pref_key_category_host"
        android:title="@string/title_category_host" >
        <fr.bmigette.crocoschedulerconsoleandroid.EditTextPreferenceWithSummary
            android:defaultValue="@string/default_pref_host_1"
            android:key="pref_key_host_1"
            android:summary="@string/default_pref_host_1"
            android:title="@string/title_pref_host_1" />

        <fr.bmigette.crocoschedulerconsoleandroid.EditTextPreferenceWithSummary
            android:defaultValue="@string/default_pref_port_1"
            android:key="pref_key_port_1"
            android:summary="@string/default_pref_port_1"
            android:title="@string/title_pref_port_1" />

        <fr.bmigette.crocoschedulerconsoleandroid.EditTextPreferenceWithSummary
            android:defaultValue="@string/default_pref_pass_1"
            android:key="pref_key_pass_1"
            android:summary="@string/default_pref_pass_1"
            android:title="@string/title_pref_pass_1" />

    </PreferenceCategory>
</PreferenceScreen>

無需進行那些額外的編碼,我已經遇到了這個問題並通過一行解決了它。

經過數小時查看此問題和其他類似問題的所有答案后,我發現了無需擴展ListPreference的最簡單方法,您可以共同extends PreferenceActivity ,請參見下面的代碼。

public class UserSettingsActivity extends PreferenceActivity 
{
    ListPreference listpref;

    @Override
    public void onCreate(Bundle savedInstenceState)
    {
        super.onCreate(savedInstenceState);
        addPreferencesFromResource(R.xml.settings);
        listpref = (ListPreference)findPreference("prefDefaultCurrency");

        listpref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() 
        {           
            @Override
            public boolean onPreferenceChange(Preference preference, Object value) {
            // TODO Auto-generated method stub

            listpref.setSummary(listpref.getEntries()[Integer.parseInt(value.toString())]);
            return true;
        }
    });

就是這樣,只需一行,您所要做的就是獲取從onPreferenceChange(Preference preference, Object value)傳遞的值,將其解析為 integer 並將其傳遞給listpref.setSummary(listpref.getEntries()[Integer.parseInt(value.toString())]);

參考接受的答案 (@Michael),如果您修改 MyListPreference 以添加 onPreferenceChangeListener:

public MyListPreference(final Context context, final AttributeSet attrs) {
    super(context, attrs);
    setOnPreferenceChangeListener(this);
}

並讓監聽器實現返回 true:

public boolean onPreferenceChange(Preference preference, Object newValue) {
    // Do other stuff as needed, e.g. setTitle()
    return true;
}

摘要“%s”始終解析為最新設置。 否則,它始終具有默認設置。

不要忘記添加工具:

public class MyListPreference extends ListPreference implements Preference.OnPreferenceChangeListener

Kotlin 中最簡單的方法

findPreference<ListPreference>(getString(R.string.pref_some_key)).apply {
    summary = entry
    setOnPreferenceChangeListener { _, newValue ->
        summary = entries[entryValues.indexOf(newValue)]
        return@setOnPreferenceChangeListener true
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM