Question

Ok, I know there have been a lot of questions about SharedPreferences in Android asked before, and I did manage to get quite far, but since I'm kinda new to SharedPreferences I don't know the last few steps to get it to work.

In my MainActivity I have the following:

public class MainActivity extends ActionBarActivity
{
    ...

    // Public static MainActivity so we can use findViewById from MyPrefsActivity
    public static MainActivity mActivity;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...

        mActivity = this;
    }

    ...

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        switch(id){
            case R.id.action_settings:
                startActivity(new Intent(this, MyPrefsActivity.class));
                return true;
        }
        return false;
    }
}

And this is MyPrefsActivity.java:

package com.example.checkboxoptionsv2;

import android.annotation.TargetApi;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.ImageButton;

public class MyPrefsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener
{
    private static int prefs = R.xml.settings;
    private ImageButton cbButton, spinnerButton, popupButton;
    private final String LIST_PREFERENCE = "prefCheckboxOption";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        try{
            getClass().getMethod("getFragmentManager");
            AddResourceApi11AndGreater();
        }
        catch(NoSuchMethodException e){ // Android API < 11
            AddResourceApiLessThan11();
        }

        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        preferences.registerOnSharedPreferenceChangeListener(this);
*       ListPreference listPreference = (ListPreference) findPreference(LIST_PREFERENCE);
        if(listPreference.getValue() == null)
            listPreference.setValue("0");

        cbButton = (ImageButton) MainActivity.mActivity.findViewById(R.id.ibtnCheckbox);
        spinnerButton = (ImageButton) MainActivity.mActivity.findViewById(R.id.ibtnSpinner);
        popupButton = (ImageButton) MainActivity.mActivity.findViewById(R.id.ibtnPopup);

        setChosenPreference(0);
    }

    private void setChosenPreference(int chosen_value){
        // First put all Visibilities on GONE
        cbButton.setVisibility(View.GONE);
        spinnerButton.setVisibility(View.GONE);
        popupButton.setVisibility(View.GONE);

        // Then turn the chosen on VISIBLE again
        switch(chosen_value){
            case 0: // Multi-Click CheckBox
            default:
                cbButton.setVisibility(View.VISIBLE);
                break;
            case 1: // Dropdown CheckBox
                spinnerButton.setVisibility(View.VISIBLE);
                break;
            case 2: // Pop-up CheckBox
                popupButton.setVisibility(View.VISIBLE);
                break;          
        }
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if(key.equals(LIST_PREFERENCE)){
            ListPreference listPreference = (ListPreference) findPreference(key); // LIST_PREFERENCE
            listPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
                @Override
                public boolean onPreferenceChange(Preference preference, Object newValue) {
                    int chosen_option = Integer.valueOf((String) newValue);
                    setChosenPreference(chosen_option);
                    return false;
                }
            });
        }
        else{
            // Other settings
        }
    }

    @SuppressWarnings("deprecation")
    protected void AddResourceApiLessThan11(){
        addPreferencesFromResource(prefs);
    }

    @TargetApi(11)
    protected void AddResourceApi11AndGreater(){
*       MyPreferenceFragment pf = new MyPreferenceFragment();
        getFragmentManager().beginTransaction().replace(android.R.id.content, pf).commit();
    }

    @TargetApi(11)
    public static class MyPreferenceFragment extends PreferenceFragment{
        @Override
        public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
*           addPreferencesFromResource(MyPrefsActivity.prefs); // outer class
            // private members seem to be visible for inner class, and
            // making it static made things so much easier
        }
    }
}

And the settings.xml:

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

    <PreferenceCategory android:title="@string/checkbox_options_title" >
        <ListPreference
                android:key="prefCheckboxOption"
                android:title="@string/pref_checkbox_option"
                android:summary="@string/checkbox_options_summary"
                android:entries="@array/checkbox_options"
                android:entryValues="@array/checkbox_option_values" />

    </PreferenceCategory>

</PreferenceScreen>

and arrays.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="checkbox_options">
        <item>CheckBox as Multi-Click</item>
        <item>CheckBox as Dropdown</item>
        <item>CheckBox as Pop-up</item>
    </string-array>
    <string-array name="checkbox_option_values">
        <item>0</item>
        <item>1</item>
        <item>2</item>
    </string-array>
</resources>

(Of course I've also included the MyPrefsActivity in the AndroidManifest.xml)


My goal is to make one of the three checkbox-option (found in the setChosenPreference method) VISIBLE, and the other two GONE, based on the preference selected in the ListPreference.

Right now the Listpreference in both the onCreate() method and onSharedPreferenceChanged() is null and giving a NullPointerException. So I set some breakpoints (see the three " * ") and the reason they are null is because the third " * " (in the static class PF) isn't called.

The addPreferencesFromResources should be called before using findPreference, otherwise it will return null. Does anyone know why during debugging I do get to the second " * " in the AddResourceApi11AndGreater() method, but I'm not getting to the third one in the MyPreferenceFragment-class onCreate method() ?.. the onCreate isn't called at all..

Also, does the rest of my code seems ok(-ish) or should I change something in order to make it work as I intended?

Thanks in advance for the responses.

TL;DR: MyPreferenceFragment instantion is created successfully, but it's @Override onCreate method is never called.


EDIT 1: Ok, I did found the problem: When I added addPreferencesFromResource(prefs) in the activity's onCreate method as a debug-test, I found out that the MyPreferenceFragment-class is indeed being initialized, then it finishes the activity's onCreate method (which would have failed at findPreference() if I didn't added the addPreferencesFromResource(prefs) test-line), and only after the activity's onCreate method is completely finished, it goes to the MyPreferenceFragment's onCreate method.

Is there a way to let the PreferenceFrament's onCreate method go first, while in the middle of the activity's onCreate method, so after AddResourceApi11AndGreater() but before findPreference(LIST_PREFERENCE)?

Was it helpful?

Solution

Move your logic to PF, don't do things in PreferenceActivity. There are also changes in the way of listening to the preferences changes. Check the code.

public class MyPrefsActivity extends PreferenceActivity {
    private static int prefs = R.xml.settings;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        try{
            getClass().getMethod("getFragmentManager");
            AddResourceApi11AndGreater();
        }
        catch(NoSuchMethodException e){ // Android API < 11
            AddResourceApiLessThan11();
        }
    }

    @SuppressWarnings("deprecation")
    protected void AddResourceApiLessThan11(){
        addPreferencesFromResource(prefs);
    }

    @TargetApi(11)
    protected void AddResourceApi11AndGreater(){
        getFragmentManager().beginTransaction().replace(android.R.id.content,
                new PF()).commit();
    }

    @TargetApi(11)
    public static class PF extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
        private ImageButton cbButton, spinnerButton, popupButton;
        private final String LIST_PREFERENCE = "prefCheckboxOption";

        @Override
        public void onCreate(final Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(MyPrefsActivity.prefs); // outer class
            // private members seem to be visible for inner class, and
            // making it static made things so much easier

            SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
            preferences.registerOnSharedPreferenceChangeListener(this);
            ListPreference listPreference = (ListPreference) findPreference(LIST_PREFERENCE);
            if(listPreference.getValue() == null)
                listPreference.setValue("0");



            cbButton = (ImageButton) MainActivity.mActivity.findViewById(R.id.ibtnCheckbox);
            spinnerButton = (ImageButton) MainActivity.mActivity.findViewById(R.id.ibtnSpinner);
            popupButton = (ImageButton) MainActivity.mActivity.findViewById(R.id.ibtnPopup);

            setChosenPreference(Integer.valueOf(preferences.getString(LIST_PREFERENCE, "0")));
        }

        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            int chosen_option = Integer.valueOf(sharedPreferences.getString(key, "0"));
            setChosenPreference(chosen_option);
        }

        private void setChosenPreference(int chosen_value){
            // First put all Visibilities on GONE
            cbButton.setVisibility(View.GONE);
            spinnerButton.setVisibility(View.GONE);
            popupButton.setVisibility(View.GONE);

            // Then turn the chosen on VISIBLE again
            switch(chosen_value){
                case 0: // Multi-Click CheckBox
                default:
                    cbButton.setVisibility(View.VISIBLE);
                    break;
                case 1: // Dropdown CheckBox
                    spinnerButton.setVisibility(View.VISIBLE);
                    break;
                case 2: // Pop-up CheckBox
                    popupButton.setVisibility(View.VISIBLE);
                    break;
            }
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top