[ACCEPTED]-How to fill ListPreference dynamically when onPreferenceClick is triggered?-android-preferences

Accepted answer
Score: 58

You are getting the exception because your 14 ListPreference object is not initialized 13 - you either need to set entries and entryValues attributes 12 in your XML or do it programatically in 11 onCreate().

If if you need to change the items in 10 the list dynamically after the initial ListPreference 9 object has been initialized then you will 8 need to attach the OnPreferenceClickListener directly to the ListPreference 7 object. Use the key you have specified in 6 the XML to get a handle to the preference.

Since 5 the code to populate the entries and entryValues arrays will 4 have to be run both in onCreate() and in onPreferenceClick, it makes 3 sense to extract it to a separate method 2 - 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 1 example from google's DeskClock app:

Score: 8

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

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

Since 4 the code to populate the entries and entryValues arrays will 3 have to run both in onCreate() and in onPreferenceClick, it makes sense 2 to extract it to a separate method - setListPreferenceData() in 1 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>
Score: 1

I solved the problem my extending the ListPreference. It 5 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 4 the name to my class in the XML.

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

And then 3 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 2 right away. Actually, I never expected it 1 would be done so easily.

Score: 0

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();

}

0

More Related questions