likejudo
likejudo

Reputation: 3735

My ListPreference does not persist values when changing screen orientation

I have been stuck on this for days and tried different workarounds. When I change screen orientation, the preference summary loses its value.

I have a custom ListPreference which when user clicks, pops up two choices for buddy - myself, and some other (in the actual program, user selects a buddy from Contacts).

I set the summary to the selected buddy's email address.

clicking preference pops up list preference which, depending on what is clicked, shows myself, or contacts picker to select a buddy.

enter image description here

'myself' was selected

enter image description here

flipping phone loses buddy

enter image description here

Here is a working program stripped to show the essentials.

class BuddyPreference2

public class BuddyPreference2 extends ListPreference {
    String buddy;
    private static final String TAG = "REGU";

    public BuddyPreference2(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    protected void onDialogClosed(boolean positiveResult) {
        if (positiveResult) {
            persistString((String) buddy);
        }
        super.onDialogClosed(positiveResult);
    }
    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        super.onSetInitialValue(restoreValue, defaultValue);
        if (restoreValue) {
            // Restore existing state
            buddy = this.getPersistedString("none set");
        } else {
            // Set default state from the XML attribute
            buddy = (String) defaultValue;
            persistString(buddy);
        }
    }
    /*
     * (non-Javadoc)
     * 
     * @see android.preference.ListPreference#setValue(java.lang.String)
     */
    @Override
    public void setValue(String value) {
        String s = new String(value);
        super.setValue(s);
    }
    @Override
    protected View onCreateDialogView() {
        View view = super.onCreateDialogView();

        return view;
    }
}

user_prefs.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    android:key="@+id/pref_screen" >
    <com.mypreferences.BuddyPreference2
        android:entries="@array/buddy_entry"
        android:entryValues="@array/buddy_value"
        android:key="buddy_entry"
        android:summary="my buddy"
        android:title="my buddy" />
</PreferenceScreen>

class EditAlertPreferencesActivity

public class EditAlertPreferencesActivity extends Activity {


    static final String BUDDY = "buddy_entry";

    static final String TAG = "REGU";
    private static final int CONTACT_PICKER_RESULT = 1001;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.user_prefs_fragment);
    }

    // Fragment that displays the mesg preference
    public static class UserPreferenceFragment extends PreferenceFragment {

        protected static final String TAG = "REGU";
        private OnSharedPreferenceChangeListener mListener;
        private Preference buddyPreference;

        String myEmailAddress;

        String getMyEmailAddress() {
                    return "Myself" + " <[email protected]>";
        }

        public void setBuddySummary(String s) {
            buddyPreference.setSummary(s);
        }


        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            myEmailAddress = getMyEmailAddress();

            // Load the preferences from an XML resource
            addPreferencesFromResource(R.xml.user_prefs);

            buddyPreference = (Preference) getPreferenceManager().findPreference(BUDDY);

            buddyPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
                @Override
                public boolean onPreferenceChange(Preference preference, Object newValue) {
                    String buddyChoice = (String) newValue;
                    if (buddyChoice.equals(getString(R.string.select))) {
                        Toast.makeText(getActivity(), "pick a contact", Toast.LENGTH_SHORT);
                        pickContact();
                    } else {
                        buddyPreference.setSummary(myEmailAddress);
                    }
                    return false;
                }
            });

            // Attach a listener to update summary when msg changes
            mListener = new OnSharedPreferenceChangeListener() {
                @Override
                public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
                        String key) {
                    if (key.equals(BUDDY)) {
                        buddyPreference.setSummary(sharedPreferences.getString(BUDDY, "none set"));
                    } else {
                        Log.e(TAG, "error; I do not recognize key " + key);
                    }
                }
            };

            // Get SharedPreferences object managed by the PreferenceManager for
            // this Fragment
            SharedPreferences prefs = getPreferenceManager().getSharedPreferences();

            // Register a listener on the SharedPreferences object
            prefs.registerOnSharedPreferenceChangeListener(mListener);

            // Invoke callback manually to display the msg
            mListener.onSharedPreferenceChanged(prefs, BUDDY);
        }

        /*
         * (non-Javadoc)
         * 
         * @see android.preference.PreferenceFragment#onCreateView(android.view.
         * LayoutInflater, android.view.ViewGroup, android.os.Bundle)
         */
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            return super.onCreateView(inflater, container, savedInstanceState);
        }

        public void pickContact() {
                            String buddyEmailAddress = "Some Buddy " + " <[email protected]>";
                            setBuddySummary(buddyEmailAddress);
        }
    }
}

user_prefs_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.mypreferences.EditAlertPreferencesActivity$UserPreferenceFragment"
    android:orientation="vertical" 
    android:id="@+id/userPreferenceFragment">

</fragment>

arrays.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="buddy_entry">
        <item>myself</item>
        <item>select a contact</item>
    </string-array>
    <string-array name="buddy_value">
        <item>myself</item>
        <item>select</item>
    </string-array>
</resources>

class PreferencesActivityExample

public class PreferencesActivityExample extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Open a User Preferences Entry Activity 
        final Button button = (Button) findViewById(R.id.check_pref_button);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(
                        PreferencesActivityExample.this,
                        EditAlertPreferencesActivity.class));
            }
        });

    }
}

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="select">select</string>
</resources>

Upvotes: 0

Views: 1812

Answers (2)

Huy Nguyen
Huy Nguyen

Reputation: 1109

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final ListPreference listPreferenceCategory = (ListPreference) findPreference("pref_list_category");
    listPreferenceCategory.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            String category = (String) newValue;
            CharSequence[] listEntries = listPreferenceCategory.getEntries();
            int indexValue = listPreferenceCategory.findIndexOfValue(category);
            listPreferenceCategory.setSummary(listEntries[indexValue]);
            return true;
        }
    });
}

In xml:

 <ListPreference
        android:dialogTitle="@string/pref_category"
        android:entries="@array/categories"
        android:summary="@string/pref_category"
        android:entryValues="@array/categories_value"
        android:key="pref_list_category"
        android:title="@string/pref_category"/>

That is my worked code. Try it !

Upvotes: 0

Libin
Libin

Reputation: 17095

Issue is that the Preference value selected on the dialog is not saved/updated. You can easily verify this Close the Activity and launch gain. You will still see the default value , noting to do with orientation change.

FIX: You need to return true to update the new value in preference.

@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
    // do all your other stuff here            
    return true;
}

True to update the state of the Preference with the new value.

Upvotes: 9

Related Questions