How to populate a ListPreference dynamically when running onPreferenceClick?

I have a preference function that has language like ListPreference , which displays a list of available languages. I can populate the list when onCreate is called, but I want to populate 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 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 did not find a result! An exception occurs every time I click on this list.

+21
android android-preferences
Jun 24 '11 at 23:23
source share
3 answers

You get an exception because the ListPreference object is not fully initialized - you either need to set the entries and entryValues in your XML, or do it programmatically in onCreate() .

If you want to dynamically change the items in the list after initializing the original ListPreference object, you will need to bind OnPreferenceClickListener directly to the ListPreference object. Use the key you specified in XML to get a preference descriptor.

Since the code for filling in the arrays of entries and entryValues must be run both in onCreate() and in onPreferenceClick , it makes sense to extract it in a separate method - setListPreferenceData() , 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); } } 
+36
Dec 11
source share

Using PreferenceFragment and JAVA , rather than PreferenceActivity and XML , as shown in https://stackoverflow.com/a/126754/ ... on which this answer is based on:

If you want to dynamically change the items in the list after initializing the original ListPreference object, you will need to bind OnPreferenceClickListener directly to the ListPreference object. Use the key you have specified in the JAVA source (like CUSTOM_LIST ) to get a preference descriptor.

Since the code for filling in the arrays of entries and entryValues must be run both in onCreate() and in onPreferenceClick , it makes sense to extract it in a separate method - setListPreferenceData() , 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> 
+2
Apr 28 '16 at 3:32
source share

I solved the problem with the ListPreference extension. 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 XML.

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

And then I just did it in 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. In fact, I never expected this to be done so easily.

0
Sep 01 '17 at 12:38 on
source share



All Articles