Search code examples
androidonclicklistenerpreference

ListPreference onClickListener takes twice to execute


So I'm having this problem where my ListPreference takes two clicks upon it, to actually do what's in the onClick listener. Here's my code

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    final ListPreference prefListThemes = (ListPreference) findPreference("prefMaterialThemes");
    prefListThemes.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
        @Override
        public boolean onPreferenceClick(Preference preference) {
            Toast.makeText(getApplicationContext(), "test", Toast.LENGTH_SHORT).show();
            System.out.println("Test prntln");
            // Restart Activity to apply Theme
            Intent intent = new Intent(getApplicationContext(), MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
            startActivity(intent);
            return false;
        }
    });

As you can see what I'm trying to do is just a simple restart of the app to apply my theme. At first I thought it might be that intent code causing the problem, but even when I have just a toast in that onclick listener you still have to click the list preference, select an option, then click the preference again, and select the option once more for it to actually do anything. If you could help that would be great. Thank You!

SettingsActivity which gets the preferences from preferences.xml

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.support.v4.content.IntentCompat;
import android.widget.Toast;

import com.iliakplv.notes.R;
import com.iliakplv.notes.gui.main.LauncherActivity;
import com.iliakplv.notes.gui.main.MainActivity;

import java.util.List;

public class SettingsActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {

    private static final int PREFERENCES = R.xml.preferences;

    private final static String PREFS_LIST_OF_THEMES = "prefMaterialThemes";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //noinspection deprecation
        addPreferencesFromResource(PREFERENCES);
        PreferenceManager.setDefaultValues(this, PREFERENCES, false);

        // These 3 lines are required for the onSharedPreferenceChanged method
        Context context = getApplicationContext();
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
        settings.registerOnSharedPreferenceChangeListener(this);
        // End
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {

        final CheckBoxPreference prefDarkThemeCB = (CheckBoxPreference) findPreference("prefDarkTheme");
        prefDarkThemeCB.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                if (prefDarkThemeCB.isChecked()) {
                    // Restart Activity to apply Theme
                    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
                    startActivity(intent);
                } else if (prefDarkThemeCB.isChecked() == false) {
                    // Also restart activity to apply default theme
                    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
                    startActivity(intent);
                }
                return false;
            }
        });

        final ListPreference prefListThemes = (ListPreference) findPreference("prefMaterialThemes");
        prefListThemes.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                Toast.makeText(getApplicationContext(), "toast", Toast.LENGTH_SHORT).show();
                System.out.println("Toasted");
                // Restart Activity to apply Theme
                Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
                startActivity(intent);
                return false;
            }
        });

        final CheckBoxPreference prefRequirePasswordCB = (CheckBoxPreference) findPreference("prefEnablePasswordLock");
        prefRequirePasswordCB.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                if (prefRequirePasswordCB.isChecked()) {
                    EditTextPreference prefUsersPass = (EditTextPreference) findPreference("prefPassword");
                    // Check to see if the users password is empty before allowing them to check the require password box
                    if (prefUsersPass.getText().toString().isEmpty()) {
                        prefRequirePasswordCB.setChecked(false);
                        Toast.makeText(getApplicationContext(), R.string.password_required, Toast.LENGTH_SHORT).show();
                        //System.out.println("Empty password");
                    } else if (prefUsersPass.getText().toString().trim().length() == 0) {
                        // The above line checks to see if the User's pass is all spaces :p
                        prefRequirePasswordCB.setChecked(false);
                        Toast.makeText(getApplicationContext(), R.string.password_required, Toast.LENGTH_SHORT).show();
                        //System.out.println("Trimmed the password because they used all spaces probably and still empty");
                    } else {
                        Toast.makeText(getApplicationContext(), R.string.password_has_been_set, Toast.LENGTH_SHORT).show();
                        //System.out.println("kapow! they have a password and its: " + prefUsersPass.getText().toString());
                    }
                }
                return false;
            }
        });

    }

}

Preferences.xml

<?xml version="1.0" encoding="utf-8"?>

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory android:title="@string/security_pref_category">
        <CheckBoxPreference
            android:defaultValue="false"
            android:key="prefEnablePasswordLock"
            android:summary="@string/pref_require_password_for_app_description"
            android:title="@string/pref_require_password_for_app" />
        <EditTextPreference
            android:defaultValue=""
            android:key="prefPassword"
            android:summary="@string/pref_password_description"
            android:title="@string/pref_password_title" />
    </PreferenceCategory>


    <PreferenceCategory android:title="@string/look_and_feel_pref_category">
        <CheckBoxPreference
            android:defaultValue="false"
            android:key="prefDarkTheme"
            android:summary="@string/pref_dark_theme_description"
            android:title="@string/pref_dark_theme" />

        <ListPreference
            android:defaultValue="1"
            android:entries="@array/pref_app_themes"
            android:entryValues="@array/pref_app_theme_values"
            android:key="prefMaterialThemes"
            android:summary="@string/pref_change_theme_description"
            android:title="@string/pref_change_theme" />


    </PreferenceCategory>

    <PreferenceCategory android:title="@string/misc_pref_category">
        <CheckBoxPreference
            android:defaultValue="true"
            android:key="linkify_note_text"
            android:summary="@string/settings_linkify_subtitle"
            android:title="@string/settings_linkify_title" />

        <Preference
            android:key="contactDevKey"
            android:summary="@string/pref_contact_developer_description"
            android:title="@string/pref_contact_developer">
            <intent
                android:action="android.intent.action.VIEW"
                android:data="mailto:[email protected]?subject=Support *Notes">
                <extra
                    android:name="android.intent.extra.TEXT"
                    android:value="" />
                <!-- Value is whats in the body, blank for now -->
            </intent>
        </Preference>

    </PreferenceCategory>


</PreferenceScreen>

Arrays.xml (used in the preference.xml file to get the entries for the list preference)

<?xml version="1.0" encoding="utf-8"?>
<resources>


    <string-array name="pref_app_themes">
        <item name="1">Default</item>
        <item name="2">Dark</item>
        <item name="3">AMOLED</item>
        <item name="4">Red</item>
        <item name="5">Pink</item>
        <item name="6">Purple</item>
        <item name="7">Deep Purple</item>
        <item name="8">Blue</item>
        <item name="9">Light Blue</item>
        <item name="10">Cyan</item>
        <item name="11">Teal</item>
        <item name="12">Green</item>
        <item name="13">Light Green</item>
        <item name="14">Lime</item>
        <item name="15">Yellow</item>
        <item name="16">Amber</item>
        <item name="17">Orange</item>
        <item name="18">Deep Orange</item>
        <item name="19">Brown</item>
        <item name="20">Grey</item>
        <item name="21">Blue Grey</item>

    </string-array>
    <string-array name="pref_app_theme_values">
        <item name="1">1</item>
        <item name="2">2</item>
        <item name="3">3</item>
        <item name="4">4</item>
        <item name="5">5</item>
        <item name="6">6</item>
        <item name="7">7</item>
        <item name="8">8</item>
        <item name="9">9</item>
        <item name="10">10</item>
        <item name="11">11</item>
        <item name="12">12</item>
        <item name="13">13</item>
        <item name="14">14</item>
        <item name="15">15</item>
        <item name="16">16</item>
        <item name="17">17</item>
        <item name="18">18</item>
        <item name="19">19</item>
        <item name="20">20</item>
        <item name="21">21</item>
    </string-array>

</resources>

Solution

  • onSharedPreferenceChanged is called once a preference is changed. When that happens you set the OnPreferenceClickListener which will be triggered once you change the value again. That's the reason your code is executed only when changing the theme value twice.

    Put this into the onCreate instead:

    final ListPreference prefListThemes = (ListPreference) findPreference("prefMaterialThemes");
    prefListThemes.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            Toast.makeText(getApplicationContext(), "toast", Toast.LENGTH_SHORT).show();
            System.out.println("Toasted");
            // Restart Activity to apply Theme
            Intent intent = new Intent(getApplicationContext(), MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
            startActivity(intent);
    
            return true;
        }
    });