如何在onPreferenceClick触发时动态填充ListPreference?

发布于 2024-11-17 08:41:01 字数 1765 浏览 3 评论 0原文

我有一个首选项活动,其语言ListPreference,它显示可用的语言列表。我可以在调用 onCreate 时填充列表,但我想在用户单击它时填充列表。

这是java代码

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

        try {
            addPreferencesFromResource(R.xml.settings);
        } catch (Exception e) {

        }

    }

    @Override
    public boolean onPreferenceClick(Preference preference) {

        if((preference instanceof ListPreference) && (preference.getKey().equals("language"))){
            ListPreference lp = (ListPreference)preference;
            CharSequence[] entries = { "English", "French" };
            CharSequence[] entryValues = {"1" , "2"};
            lp.setEntries(entries);
            lp.setDefaultValue("1");
            lp.setEntryValues(entryValues);
            return true;
        }
        return false;

    }
}

这是settings.xml(首选项):

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
  xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory android:title="General Settings">
        <CheckBoxPreference android:key="enabled"  android:title="Application Status" android:summary="Enable or disable the application" />
         <ListPreference 
         android:key="language" 
         android:title="Language"
         android:dialogTitle="Application language" 
         android:summary="Select the Application language"
         />
    </PreferenceCategory>
</PreferenceScreen>

我搜索但没有找到结果!每次我单击该列表时都会发生异常。

I have a preference activity that has a language as ListPreference which displays the available language list. I can fill the list when onCreate is called, but I want to fill the list when the user clicks on it.

this is the java code :

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

        try {
            addPreferencesFromResource(R.xml.settings);
        } catch (Exception e) {

        }

    }

    @Override
    public boolean onPreferenceClick(Preference preference) {

        if((preference instanceof ListPreference) && (preference.getKey().equals("language"))){
            ListPreference lp = (ListPreference)preference;
            CharSequence[] entries = { "English", "French" };
            CharSequence[] entryValues = {"1" , "2"};
            lp.setEntries(entries);
            lp.setDefaultValue("1");
            lp.setEntryValues(entryValues);
            return true;
        }
        return false;

    }
}

and this is the settings.xml (preference) :

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
  xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory android:title="General Settings">
        <CheckBoxPreference android:key="enabled"  android:title="Application Status" android:summary="Enable or disable the application" />
         <ListPreference 
         android:key="language" 
         android:title="Language"
         android:dialogTitle="Application language" 
         android:summary="Select the Application language"
         />
    </PreferenceCategory>
</PreferenceScreen>

I searched but found no result! An exception occurs every time I click on that list.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

蓝颜夕 2024-11-24 08:41:01

您收到异常是因为您的 ListPreference 对象未初始化 - 您需要在 XML 中设置 entriesentryValues 属性,或者在 onCreate() 中以编程方式执行此操作 或在 onCreatePreferences() 中(例如,当使用 androidx.preference.PreferenceFragmentCompat 时)。

如果您需要在初始化初始 ListPreference 对象后动态更改列表中的项目,则需要在 ListPreference 对象上设置 OnPreferenceClickListener。使用您在 XML 中指定的键来获取首选项的句柄。

由于填充 entriesentryValues 数组的代码必须在 onCreate()onPreferenceClick 中运行>,将其提取到单独的方法 - setListPreferenceData() 以避免重复是有意义的。

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

        try {
            addPreferencesFromResource(R.xml.settings);
        } catch (Exception e) {

        }

        final ListPreference listPreference = (ListPreference) findPreference("language");

        // THIS IS REQUIRED IF YOU DON'T HAVE 'entries' and 'entryValues' in your XML
        setListPreferenceData(listPreference);

        listPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                    
                setListPreferenceData(listPreference);
                return false;
            }
        });
    }

    protected static void setListPreferenceData(ListPreference lp) {
            CharSequence[] entries = { "English", "French" };
            CharSequence[] entryValues = {"1" , "2"};
            lp.setEntries(entries);
            lp.setDefaultValue("1");
            lp.setEntryValues(entryValues);
    }
}

这里是来自 google DeskClock 应用程序:

You are getting the exception because your ListPreference object is not initialized - you either need to set entries and entryValues attributes in your XML or do it programatically in onCreate() or in onCreatePreferences() (e.g. when using androidx.preference.PreferenceFragmentCompat).

If if you need to change the items in the list dynamically after the initial ListPreference object has been initialized then a OnPreferenceClickListener needs to be set on the ListPreference object. Use the key you have specified in the XML to get a handle to the preference.

Since the code to populate the entries and entryValues arrays will have to be run both in onCreate() and in onPreferenceClick, it makes sense to extract it to a separate method - setListPreferenceData() in order to avoid duplication.

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

        try {
            addPreferencesFromResource(R.xml.settings);
        } catch (Exception e) {

        }

        final ListPreference listPreference = (ListPreference) findPreference("language");

        // THIS IS REQUIRED IF YOU DON'T HAVE 'entries' and 'entryValues' in your XML
        setListPreferenceData(listPreference);

        listPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                    
                setListPreferenceData(listPreference);
                return false;
            }
        });
    }

    protected static void setListPreferenceData(ListPreference lp) {
            CharSequence[] entries = { "English", "French" };
            CharSequence[] entryValues = {"1" , "2"};
            lp.setEntries(entries);
            lp.setDefaultValue("1");
            lp.setEntryValues(entryValues);
    }
}

Here is another example from google's DeskClock app:

我偏爱纯白色 2024-11-24 08:41:01

使用PreferenceFragment & JAVA设置键而不是PreferenceActivity & XML,如 https://stackoverflow.com/a/13828912/1815624< 所示/a>,这个答案基于:

如果您想要的是能够在初始化初始 ListPreference 对象后动态更改列表中的项目,那么您将需要附加OnPreferenceClickListener 直接指向 ListPreference 对象。使用您在 JAVA 源代码中指定的密钥(如 CUSTOM_LIST)来获取首选项的句柄。

由于填充 entriesentryValues 数组的代码必须在 onCreate()onPreferenceClick 中运行,将其提取到单独的方法 - setListPreferenceData() 以避免重复是有意义的。

/**
 * This fragment shows data and sync preferences only. It is used when the
 * activity is showing a two-pane settings UI.
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class myCustomPreferenceFragment extends PreferenceFragment {

    final private String CUSTOM_LIST= "custom_list";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.pref_custom_frag);

        PreferenceCategory targetCategory = (PreferenceCategory) findPreference("CUSTOM_FRAG");

        final ListPreference lp = setListPreferenceData((ListPreference) findPreference(CUSTOM_LIST), getActivity());

        lp.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {

                setListPreferenceData(lp, getActivity());
                return false;
            }
        });
        setHasOptionsMenu(true);
        targetCategory.addPreference(lp);

        bindPreferenceSummaryToValue(targetCategory);
        bindPreferenceSummaryToValue(lp);
    }

    protected ListPreference setListPreferenceData(ListPreference lp, Activity mActivity) {
        CharSequence[] entries = { "One", "Two", "Three" };
        CharSequence[] entryValues = { "1", "2", "3" };
        if(lp == null)
            lp = new ListPreference(mActivity);
        lp.setEntries(entries);
        lp.setDefaultValue("1");
        lp.setEntryValues(entryValues);
        lp.setTitle("Number Of blahs");
        lp.setSummary(lp.getEntry());
        lp.setDialogTitle("Number of Blah objects");
        lp.setKey(CUSTOM_LIST);
        return lp;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == android.R.id.home) {
            startActivity(new Intent(getActivity(), SettingsActivity.class));
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

XML 布局:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:key="CUSTOM_FRAG"
        android:title="Some Options">

    </PreferenceCategory>
</PreferenceScreen>

Using PreferenceFragment & JAVA set key rather than PreferenceActivity & XML as shown in https://stackoverflow.com/a/13828912/1815624, which this answer is based on:

If what you want is to be able to change the items in the list dynamically after the initial ListPreference object has been initialized then you will need to attach the OnPreferenceClickListener directly to the ListPreference object. Use the key you have specified in the JAVA source (as CUSTOM_LIST) to get a handle to the preference.

Since the code to populate the entries and entryValues arrays will have to run both in onCreate() and in onPreferenceClick, it makes sense to extract it to a separate method - setListPreferenceData() in order to avoid duplication.

/**
 * This fragment shows data and sync preferences only. It is used when the
 * activity is showing a two-pane settings UI.
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class myCustomPreferenceFragment extends PreferenceFragment {

    final private String CUSTOM_LIST= "custom_list";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.pref_custom_frag);

        PreferenceCategory targetCategory = (PreferenceCategory) findPreference("CUSTOM_FRAG");

        final ListPreference lp = setListPreferenceData((ListPreference) findPreference(CUSTOM_LIST), getActivity());

        lp.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {

                setListPreferenceData(lp, getActivity());
                return false;
            }
        });
        setHasOptionsMenu(true);
        targetCategory.addPreference(lp);

        bindPreferenceSummaryToValue(targetCategory);
        bindPreferenceSummaryToValue(lp);
    }

    protected ListPreference setListPreferenceData(ListPreference lp, Activity mActivity) {
        CharSequence[] entries = { "One", "Two", "Three" };
        CharSequence[] entryValues = { "1", "2", "3" };
        if(lp == null)
            lp = new ListPreference(mActivity);
        lp.setEntries(entries);
        lp.setDefaultValue("1");
        lp.setEntryValues(entryValues);
        lp.setTitle("Number Of blahs");
        lp.setSummary(lp.getEntry());
        lp.setDialogTitle("Number of Blah objects");
        lp.setKey(CUSTOM_LIST);
        return lp;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == android.R.id.home) {
            startActivity(new Intent(getActivity(), SettingsActivity.class));
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

XML layout:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:key="CUSTOM_FRAG"
        android:title="Some Options">

    </PreferenceCategory>
</PreferenceScreen>
把时间冻结 2024-11-24 08:41:01

我解决了扩展 ListPreference 的问题。很简单。

public class DListPref extends ListPreference
{
    public interface LoadingListener
    {
        void setData(ListPreference lp);
    }

    LoadingListener TheLL;

    public void setLoadingListener(LoadingListener l)
    {
        TheLL = l;
    }

    @Override
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder)
    {
        if(TheLL!=null)
        {
            TheLL.setData(this);
        }
        super.onPrepareDialogBuilder(builder);
    }

    //Do not mind the rest of this class, as they are auto-generated boilerplate code.
    public DListPref(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public DListPref(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }

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

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

然后我只是在 XML 中将名称更改为我的类。

<my.company.DListPref
    android:defaultValue="-1"
    android:key="damn"
    android:title="vegetables"/>

然后我只是在 onCreate 中执行了此操作。

        DListPref lp = (DListPref) findPreference("damn");

        lp.setLoadingListener(new DListPref.LoadingListener()
        {
            @Override
            public void setData(ListPreference lp)
            {
                lp.setEntries(new String[]{"doge", "wow"});
                lp.setEntryValues(new String[] {"1", "2"});
                lp.setDefaultValue("1");
            }
        });

马上就开始工作了。事实上,我没想到这件事会这么容易完成。

I solved the problem my extending the ListPreference. It was very simple.

public class DListPref extends ListPreference
{
    public interface LoadingListener
    {
        void setData(ListPreference lp);
    }

    LoadingListener TheLL;

    public void setLoadingListener(LoadingListener l)
    {
        TheLL = l;
    }

    @Override
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder)
    {
        if(TheLL!=null)
        {
            TheLL.setData(this);
        }
        super.onPrepareDialogBuilder(builder);
    }

    //Do not mind the rest of this class, as they are auto-generated boilerplate code.
    public DListPref(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public DListPref(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }

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

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

And then I just changed the name to my class in the XML.

<my.company.DListPref
    android:defaultValue="-1"
    android:key="damn"
    android:title="vegetables"/>

And then I simply did this at the onCreate.

        DListPref lp = (DListPref) findPreference("damn");

        lp.setLoadingListener(new DListPref.LoadingListener()
        {
            @Override
            public void setData(ListPreference lp)
            {
                lp.setEntries(new String[]{"doge", "wow"});
                lp.setEntryValues(new String[] {"1", "2"});
                lp.setDefaultValue("1");
            }
        });

Worked right away. Actually, I never expected it would be done so easily.

吃→可爱长大的 2024-11-24 08:41:01

这就是我必须做的才能让我的工作成功

    public static class MyPreferenceFragment extends PreferenceFragment
{
    @Override
    public void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.pref_general);
        PreferenceCategory targetCategory = (PreferenceCategory) findPreference("CUSTOM_FRAG");

        //final Preference pref;
        //pref = findPreference("example_list1");
        final ListPreference lp = setListPreferenceDataSocieties((ListPreference) findPreference("custom1"), getActivity());
        final ListPreference lp2 = setListPreferenceDataRoutes((ListPreference) findPreference("custom2"), getActivity());
        final ListPreference lp3 = setListPreferenceDataCoolers((ListPreference) findPreference("custom3"), getActivity());



        setHasOptionsMenu(true);
        targetCategory.addPreference(lp);
        targetCategory.addPreference(lp2);
        targetCategory.addPreference(lp3);

        bindPreferenceSummaryToValue(targetCategory);
        bindPreferenceSummaryToValue(lp);
        bindPreferenceSummaryToValue(lp2);
        bindPreferenceSummaryToValue(lp3);
    }

    protected ListPreference setListPreferenceDataSocieties(ListPreference lp, Activity mActivity) {
        CharSequence[] entries = { "One", "Two", "Three" };
        CharSequence[] entryValues = { "1", "2", "3" };
        if(lp == null)
            lp = new ListPreference(mActivity);
        lp.setEntries(entries);
        lp.setDefaultValue("1");
        lp.setEntryValues(entryValues);
        lp.setTitle("Origin Society");
        lp.setSummary(lp.getEntry());
        lp.setDialogTitle("Registered Societies");
        lp.setKey("society_list");
        return lp;
    }


    protected ListPreference setListPreferenceDataRoutes(ListPreference lp, Activity mActivity) {
        CharSequence[] entries = { "One", "Two", "Three" };
        CharSequence[] entryValues = { "1", "2", "3" };
        if(lp == null)
            lp = new ListPreference(mActivity);
        lp.setEntries(entries);
        lp.setDefaultValue("1");
        lp.setEntryValues(entryValues);
        lp.setTitle("Designated Route");
        lp.setSummary(lp.getEntry());
        lp.setDialogTitle("Available Routes");
        lp.setKey("route_list");
        return lp;
    }
    protected ListPreference setListPreferenceDataCoolers(ListPreference lp, Activity mActivity) {
        CharSequence[] entries = { "One", "Two", "Three" };
        CharSequence[] entryValues = { "1", "2", "3" };
        if(lp == null)
            lp = new ListPreference(mActivity);
        lp.setEntries(entries);
        lp.setDefaultValue("1");
        lp.setEntryValues(entryValues);
        lp.setTitle("Destination Cooler");
        lp.setSummary(lp.getEntry());
        lp.setDialogTitle("Available Coolers");
        lp.setKey("cooler_list");
        return lp;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == android.R.id.home) {
            startActivity(new Intent(getActivity(), SettingsActivity.class));
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

}


boolean first_run = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    MyPreferenceFragment frag =  new MyPreferenceFragment();
    getFragmentManager().beginTransaction().replace(android.R.id.content, frag).commit();

}

This is what I had to do to make mine work

    public static class MyPreferenceFragment extends PreferenceFragment
{
    @Override
    public void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.pref_general);
        PreferenceCategory targetCategory = (PreferenceCategory) findPreference("CUSTOM_FRAG");

        //final Preference pref;
        //pref = findPreference("example_list1");
        final ListPreference lp = setListPreferenceDataSocieties((ListPreference) findPreference("custom1"), getActivity());
        final ListPreference lp2 = setListPreferenceDataRoutes((ListPreference) findPreference("custom2"), getActivity());
        final ListPreference lp3 = setListPreferenceDataCoolers((ListPreference) findPreference("custom3"), getActivity());



        setHasOptionsMenu(true);
        targetCategory.addPreference(lp);
        targetCategory.addPreference(lp2);
        targetCategory.addPreference(lp3);

        bindPreferenceSummaryToValue(targetCategory);
        bindPreferenceSummaryToValue(lp);
        bindPreferenceSummaryToValue(lp2);
        bindPreferenceSummaryToValue(lp3);
    }

    protected ListPreference setListPreferenceDataSocieties(ListPreference lp, Activity mActivity) {
        CharSequence[] entries = { "One", "Two", "Three" };
        CharSequence[] entryValues = { "1", "2", "3" };
        if(lp == null)
            lp = new ListPreference(mActivity);
        lp.setEntries(entries);
        lp.setDefaultValue("1");
        lp.setEntryValues(entryValues);
        lp.setTitle("Origin Society");
        lp.setSummary(lp.getEntry());
        lp.setDialogTitle("Registered Societies");
        lp.setKey("society_list");
        return lp;
    }


    protected ListPreference setListPreferenceDataRoutes(ListPreference lp, Activity mActivity) {
        CharSequence[] entries = { "One", "Two", "Three" };
        CharSequence[] entryValues = { "1", "2", "3" };
        if(lp == null)
            lp = new ListPreference(mActivity);
        lp.setEntries(entries);
        lp.setDefaultValue("1");
        lp.setEntryValues(entryValues);
        lp.setTitle("Designated Route");
        lp.setSummary(lp.getEntry());
        lp.setDialogTitle("Available Routes");
        lp.setKey("route_list");
        return lp;
    }
    protected ListPreference setListPreferenceDataCoolers(ListPreference lp, Activity mActivity) {
        CharSequence[] entries = { "One", "Two", "Three" };
        CharSequence[] entryValues = { "1", "2", "3" };
        if(lp == null)
            lp = new ListPreference(mActivity);
        lp.setEntries(entries);
        lp.setDefaultValue("1");
        lp.setEntryValues(entryValues);
        lp.setTitle("Destination Cooler");
        lp.setSummary(lp.getEntry());
        lp.setDialogTitle("Available Coolers");
        lp.setKey("cooler_list");
        return lp;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == android.R.id.home) {
            startActivity(new Intent(getActivity(), SettingsActivity.class));
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

}


boolean first_run = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    MyPreferenceFragment frag =  new MyPreferenceFragment();
    getFragmentManager().beginTransaction().replace(android.R.id.content, frag).commit();

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文