Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PreferenceFragment OnPreferenceClickListener() works only once

I'm implementing a custom Preference that shall behave similar to a button (the preference will open up a dialog for restoring the default values of all preferences). It's working fine if you click on the ResetPreference the dialog shows and on positive click all preference data is cleared and reset, but if you click on the ResetPreference again nothing happens. I suppose that while setting the PreferenceScreen to null and re-adding the resources something is amiss.

If you ask why I used this approach, I wanted to click on reset and directly show the result of the change, if anyone knows a better way to implement a reset please give a little example.

PS: If clicking on the ResetPreference and selecting the negative button nothing happens and the listener is still functional so it should really have something to to with deleting and re-adding the resources.

ResetPreference.java

public class ResetPreference extends Preference {

public ResetPreference(Context context, AttributeSet attrs) {
    super(context, attrs);

    setOnPreferenceClickListener(new OnPreferenceClickListener() {

        public boolean onPreferenceClick(Preference preference) {
            AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
            builder.setTitle(R.string.prefAlertDialog_Title);   
            builder.setMessage(R.string.prefAlertDialog_Message);
            builder.setPositiveButton(R.string.prefAlertDialog_Positive, new OnClickListener() {

                public void onClick(DialogInterface dialog, int which) {
                    SettingsFragment.resetSettings(getContext());   
                }
            });
            builder.setNegativeButton(R.string.prefAlertDialog_Negative, null);
            builder.create().show();

            return false;
        }
    });

}}

Then there is my custom PreferenceFragment SettingsFragment.java

public class SettingsFragment extends PreferenceFragment{

private static SettingsFragment sf = null;

 public static void resetSettings(Context ctx)
 {

    PreferenceManager
    .getDefaultSharedPreferences(ctx)
    .edit()
    .clear()
    .commit();
    PreferenceManager.setDefaultValues(ctx, R.xml.preferences, true);           

    if(sf != null)
    {
        sf.setPreferenceScreen(null);
        sf.addPreferencesFromResource(R.xml.preferences);   
    }
 }

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

        sf = this;

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

        Preference reset = (Preference) findPreference("reset");

        reset.setOnPreferenceClickListener(new OnPreferenceClickListener()
        {
            public boolean onPreferenceClick(Preference pref)
            {           

                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                builder.setTitle(R.string.prefAlertDialog_Title);   
                builder.setMessage(R.string.prefAlertDialog_Message);
                builder.setPositiveButton(R.string.prefAlertDialog_Positive, new OnClickListener() {

                    public void onClick(DialogInterface dialog, int which) {
                        PreferenceManager
                        .getDefaultSharedPreferences(getActivity().getApplicationContext())
                        .edit()
                        .clear()
                        .commit();
                        PreferenceManager.setDefaultValues(getActivity().getApplicationContext(), R.xml.preferences, true);             

                        setPreferenceScreen(null);
                        addPreferencesFromResource(R.xml.preferences);                      
                    }
                });
                builder.setNegativeButton(R.string.prefAlertDialog_Negative, null);
                builder.create().show();


                return true;
            }
        });
 } 

 @Override
public void onStop() {
    super.onStop();
    sf = null;
}}

After adding the suggestion from https://stackoverflow.com/a/24648780/3387852 everything is done in the SettingsFragment. The ResetPreference is no longer needed and the standard android Preference can be used instead.

The only code needed to implement the reset button is in this updated

SettingsFragment.java

public class SettingsFragment extends PreferenceFragment{

private void addMyResetListener() {
    Preference reset = (Preference) findPreference("reset");

    reset.setOnPreferenceClickListener(new OnPreferenceClickListener()
    {
        public boolean onPreferenceClick(Preference pref)
        {           

            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            builder.setTitle(R.string.prefAlertDialog_Title);   
            builder.setMessage(R.string.prefAlertDialog_Message);
            builder.setPositiveButton(R.string.prefAlertDialog_Positive, new OnClickListener() {

                public void onClick(DialogInterface dialog, int which) {
                    resetSettings(SettingsFragment.this.getActivity());             
                }
            });
            builder.setNegativeButton(R.string.prefAlertDialog_Negative, null);
            builder.create().show();

            return true;
        }
    });
}

public void resetSettings(Context ctx)
{   
    //Remove all Settings 
    PreferenceManager
    .getDefaultSharedPreferences(ctx)
    .edit()
    .clear()
    .commit();
    //All Settings that are empty will be loaded from default values again
    PreferenceManager.setDefaultValues(ctx, R.xml.preferences, true);           

    setPreferenceScreen(null);
    addPreferencesFromResource(R.xml.preferences);  
    addMyResetListener();
}

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

       // Load the preferences from an XML resource & add listener
       addPreferencesFromResource(R.xml.preferences);
       addMyResetListener();
} }
like image 901
Alcardis Avatar asked Oct 01 '22 09:10

Alcardis


1 Answers

When you call the setPreferenceScreen(null); all the data and listeners of the screens is removed. Then by calling addPreferencesFromResource(R.xml.preferences); you add the data but not the listeners.

So to make Preference reset to work you need to add the listener again!

I suggest you create a method

private void addMyResetListener() {
    Preference reset = (Preference) findPreference("reset");

    reset.setOnPreferenceClickListener(new OnPreferenceClickListener()
    {
        public boolean onPreferenceClick(Preference pref)
        {           

            resetSettings(SettingsFragment.this.getActivity());


            return true;
        }
    });
}

And use it after the

setPreferenceScreen(null);
addPreferencesFromResource(R.xml.preferences);
addMyResetListener();

So resetSettings changes to

 public void resetSettings(Context ctx) // also removed static
 {

    PreferenceManager
    .getDefaultSharedPreferences(ctx)
    .edit()
    .clear()
    .commit();
    PreferenceManager.setDefaultValues(ctx, R.xml.preferences, true);           

    setPreferenceScreen(null);
    addPreferencesFromResource(R.xml.preferences);   
    addMyResetListener();
 }

That way you do not need a custom preference ResetPreference

like image 133
madlymad Avatar answered Oct 05 '22 00:10

madlymad