androidpreferences

Building Preference screen in code depending on another setting


I have searched here and looked at samples but haven't yet found an answer to what is essentially a simple problem. Depending on the choice made in a preceding ListPreference, I want to build a preference screen of CheckBoxPreferences dynamically in code, which is then shown when I click on a simple preference with a click listener. The list and number of check boxes will be different in each case.

This is where I have got to so far - just a simple bit of code to test the concept in the onClick listener, but how to get the check box preference screen to appear? There must be a simple explanation why it doesn't. What am I doing wrong?

Part of my xml code:

<PreferenceCategory android:title="Filters">
    <PreferenceScreen android:key="FilterScreen"
        android:title="Filters" android:summary="Click to change filter settings">
        <ListPreference android:title="Filter type" 
            android:summary="Set to: Gliding"
            android:key="filterType"
            android:defaultValue="0"
            android:entries="@array/filterTypeOptions"
            android:entryValues="@array/filterTypeValues" />
        <CheckBoxPreference android:title=""
            android:summary="Include Aerodrome Notams"
            android:defaultValue="false" android:key="filterIncludeAerodrome" />
        <CheckBoxPreference android:title=""
            android:summary="Delete night-time Notams"
            android:defaultValue="true" android:key="filterDeleteNighttime" />
        <ListPreference android:title="Select category to change" 
            android:summary="Set to: Airspace organisation"
            android:key="filterCategory"
            android:defaultValue="0"
            android:entries="@array/filterCategoryOptions"
            android:entryValues="@array/filterCategoryValues" />
        <Preference android:title="Show filters for category"
            android:summary="Click to choose subjects to delete"
            android:key="filterShow" />
    </PreferenceScreen>
</PreferenceCategory>

The contents of "Show filters for category" will depend on the "Filter type" and "Select category to change" settings.

This is the simple test code I have for the "Show filters" click listener (cut down just to show essentials):

public class Settings extends PreferenceActivity
                  implements OnSharedPreferenceChangeListener
{
    ------
    public static final String KEY_FILTER_SHOW = "filterShow";

    ------
    private Preference mFilterShow;

    ------
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.layout.settings);

        // Get a reference to the preferences

        ------
        mFilterShow = (Preference)findPreference(KEY_FILTER_SHOW);

        ------
        // Set the click listener for  Show Filter options
        mFilterShow.setOnPreferenceClickListener(new OnPreferenceClickListener()
        {
            public boolean onPreferenceClick(Preference pref)
            {
                Context ctx = pref.getContext();
                PreferenceScreen screen =
                    pref.getPreferenceManager().createPreferenceScreen(ctx);
                CheckBoxPreference cb1 = new CheckBoxPreference(ctx);
                cb1.setTitle("This is cb1");
                cb1.setKey("cb1_key");
                cb1.setDefaultValue(false);
                screen.addPreference(cb1);
                return true;
            }
    
        });

Solution

  • OK, I have solved the problem myself, through a process of iteration! Others might find this useful.

    Just create an empty PreferenceScreen in the xml:

            <PreferenceScreen android:title="Show filters for category"
                android:summary="Click to choose subjects to delete"
                android:key="filterShow">
            </PreferenceScreen>
    

    Then in the code there is no need for the onClick listener - the contents of the screen are created in the onCreate function. Actually, since the contents of the screen need to change when the choice made in the Category list preference (see original code) changes, this needs to go in a separate function which is called both from onCreate and onSharedPreferenceChanged:

    public static final String KEY_FILTER_SHOW = "filterShow";
    ...    
    private PreferenceScreen mFilterShow;
    ...
    
    // In onCreate:
    
        // Get a reference to the PreferenceScreen
        mFilterShow =
            (PreferenceScreen)getPreferenceScreen().findPreference(KEY_FILTER_SHOW);
    
        // Now the code to create the contents of the screen
        mFilterShow.removeAll();
        CheckBoxPreference cb1 = new CheckBoxPreference(this);
        cb1.setTitle("This is cb1");
        cb1.setKey("cb1_key");
        cb1.setDefaultValue(true);
        mFilterShow.addPreference(cb1);
    

    The above is just "proof of concept". It works exactly as you would expect. In my final version, I will create an array of CheckBoxPreferences with 'new' initially, then re-use them (changing title and default) when setting up the contents of the screen for each Category choice as it changes. The number of check boxes required may be different for each category - I will create an array for the maximum number required, then add as many as I need in each case.