ListPreference onClickListener выполняется дважды

Итак, у меня возникла проблема, когда мой ListPreference делает два щелчка по нему, чтобы фактически сделать то, что находится в прослушивателе onClick. Вот мой код

@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;
        }
    });

Как видите, я пытаюсь просто перезапустить приложение, чтобы применить мою тему. Сначала я подумал, что это может быть код намерения, вызывающий проблему, но даже когда у меня есть только тост в этом прослушивателе onclick, вам все равно нужно щелкнуть параметр списка, выбрать параметр, затем снова щелкнуть параметр и выбрать параметр один раз. больше для того, чтобы на самом деле сделать что-нибудь. Если бы вы могли помочь, это было бы здорово. Спасибо!

SettingsActivity, которая получает настройки из 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;
            }
        });

    }

}

Настройки.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 (используется в файле preference.xml для получения записей для предпочтения списка)

<?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>

person Fernando    schedule 28.10.2014    source источник


Ответы (2)


onSharedPreferenceChanged вызывается после изменения предпочтения. Когда это произойдет, вы установите OnPreferenceClickListener, который будет запущен, как только вы снова измените значение. По этой причине ваш код выполняется только при двойном изменении значения темы.

Вместо этого поместите это в onCreate:

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;
    }
});
person Emanuel Moecklin    schedule 28.10.2014
comment
Я тоже так пробовал. Он делает то же самое. Я должен выбрать элемент дважды, чтобы он работал. - person Fernando; 29.10.2014
comment
Я верю вам, так как я тоже использовал его раньше, но это первый раз, когда это случилось со мной. Все мои другие настройки работают нормально, кроме этого почему-то. Копаться в каждом дюйме кода, пытаясь найти хоть что-нибудь, что могло бы сделать это. - person Fernando; 29.10.2014
comment
На самом деле, я только что протестировал его в одном из своих приложений, и он вызывается всякий раз, когда изменяется предпочтение списка (показывает тост). Код, который вы разместили, определенно не работает, поэтому, пожалуйста, попробуйте мой, даже если он у вас уже был. Может быть, у вас было (немного) иначе? - person Emanuel Moecklin; 29.10.2014
comment
Если это не работает, опубликуйте свой (новый) код еще раз, а также код, который заполняет предпочтения списка (или xml, если оттуда берутся значения) - person Emanuel Moecklin; 29.10.2014
comment
Я попробовал ваш код, он также делал это. Я обновил пост, указав свои предпочтения, preferences.xml и arrays.xml. - person Fernando; 29.10.2014
comment
Попробуйте мой подход еще раз, но на этот раз переместите prefListThemes.setOnPreferenceChangeListener в onCreate. Очевидно, что это не работает, если этот вызов находится внутри onSharedPreferenceChanged. - person Emanuel Moecklin; 29.10.2014
comment
Это немедленно запускает прослушиватель, но он не распознает ни один из переключателей в этом диалоговом окне. Он запустит код внутри метода, но он как будто не подключен. @Эмануэль Моклин - person Fernando; 29.10.2014
comment
Конечно, он не распознает новые значения, поскольку вы возвращаете false вместо true. Я изменил свой ответ, чтобы включить полный код. Поместите это в onCreate(), и я гарантирую вам, что это сработает. - person Emanuel Moecklin; 29.10.2014

На самом деле вам не нужно помещать свой код в onCreate, просто измените тип перенастройки на true.

Официальная документация: http://developer.android.com/reference/android/preference/Preference.OnPreferenceChangeListener.html Значение true, чтобы обновить состояние предпочтения новым значением.

person Rensodarwin    schedule 18.11.2014