Preferencia de conmutador – Manejo de los dos onPreferenceChange y onPreferenceClick

He estado intentando conseguir una preferencia del interruptor que trabaja en androide por medio de la cual puedo interceptar y manejar diferentemente, en ciertos casos, cuando lo ponen encendido / apagado contra cuando chascan toda la preferencia.

Esto es lo que estoy tratando de lograr: El usuario entra en las etiquetas de preferencias están desactivadas y no se almacenan las etiquetas (es decir: la preferencia de las etiquetas está vacía) El usuario activa la preferencia por las etiquetas, y puesto que no se almacenan etiquetas actualmente se inicia una actividad de búsqueda de etiquetas Para que el usuario encuentre la etiqueta. – funciona bien.

Si la etiqueta ya existe, y cambian el estado SOLAMENTE entonces actualice el valor como normal. – funciona bien

Este es mi problema: si hacen clic en la preferencia y ya tienen una etiqueta guardada, no cambie el estado (independientemente de si está habilitado o deshabilitado), inicie la actividad de búsqueda de etiquetas. – esto NO funciona.

Lo que he encontrado hasta ahora es que en el escenario final anterior, recibo una llamada a onPreferenceChanged, seguida de una llamada a onPreferenceClicked, seguida de una llamada posterior a onPreferenceChanged. Este parece ser mi problema. La primera llamada a onPreferenceChanged hace que mi oyente en Mis SharedPreferences sea llamado diciéndole que ahora está habilitado.

Si no recibí la primera llamada a onPreferenceChanged entonces no tendría un problema.

Aquí están las partes relevantes donde estoy fijando a los oyentes

SwitchPreference tagPref = (SwitchPreference) findPreference(PreferencesConstants.PREFERENCE_TAG_ENABLED); tagPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { Log.e("BLAH", "onPrefChanged....is it handled by OnClick?" + Boolean.toString(handledByClick)); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext()); boolean enabled = prefs.getBoolean(PreferencesConstants.PREFERENCE_TAG_ENABLED, false); Log.e("BLAH", "value stored in prefs? " + Boolean.toString(enabled)); if (newValue instanceof Boolean) { enabled = (Boolean) newValue; } Log.e("BLAH", "New value? " + Boolean.toString(enabled)); if (!handledByClick) { if (enabled && (currentTag == null || currentTag.isEmpty())) { Log.e("BLAH", "Enabled and CurrentTag empty!"); Intent intent = new Intent(getActivity(), TagSearchActivity.class); startActivityForResult(intent, 0); return false; // always return false, we'll handle // updating // this value manually. } else { return true; } } Log.e("BLAH", "returning false (AS IN WE HANDLED IT)."); return false; } }); tagPref.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { handledByClick = true; Log.e("BLAH", "onprefClick"); Intent intent = new Intent(getActivity(), TagSearchActivity.class); startActivityForResult(intent, 0); return true; } }); 

Aquí están las líneas de registro relevantes después de ejecutarlo con una etiqueta guardada y hacer clic en la preferencia.

 01-18 15:55:05.593: E/BLAH(13261): onPrefChanged....is it handled by OnClick?false 01-18 15:55:05.593: E/BLAH(13261): value stored in prefs? true 01-18 15:55:05.593: E/BLAH(13261): New value? false 01-18 15:55:05.613: E/DifferentClass(13261): On Shared Preferences Changed - tagEnabled 01-18 15:55:05.652: E/DifferentClass(13261): disabled TAG in cancelAlarmService 01-18 15:55:05.662: E/AnotherClass(13261): Updating Feed List. Old Size: 33, New Size: 14 01-18 15:55:05.682: E/BLAH(13261): onprefClick 01-18 15:55:05.812: E/BLAH(13261): onPrefChanged....is it handled by OnClick?true 01-18 15:55:05.812: E/BLAH(13261): value stored in prefs? false 01-18 15:55:05.822: E/BLAH(13261): New value? false 01-18 15:55:05.822: E/BLAH(13261): returning false (AS IN WE HANDLED IT). 

He estado trabajando con el mismo problema desde hace siglos y puedes hacerlo de dos maneras.

Implementación de una preferencia de conmutación con acciones personalizadas para cada evento:

  • Forevercrashed hizo algunos buenos puntos. Traté de seguirlas, pero para mí no lo hicieron. Apuesto a que funcionan, pero necesitaba más funcionalidad de una manera más fácil. Xgouchet (Second Link) utiliza encabezados y diseños xml personalizados que usan ubicaciones personalizadas y medidas (altura, witdth, relleno, etc.). Necesitaba una solución sin alterar Googles construido en el diseño generado automáticamente.

  • La manera super fácil y potente: implementar su propia SwitchPreference ! Simplemente haga que una clase extienda SwitchPreference y luego implemente / reemplace de la siguiente manera:

     public class AutoUploadSwitchPreference extends SwitchPreference { public AutoUploadSwitchPreference(Context context) { super(context); } public AutoUploadSwitchPreference(Context context, AttributeSet attrs) { super(context, attrs); } public AutoUploadSwitchPreference(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onClick() { //super.onClick(); THIS IS THE IMPORTANT PART! } 

Al sobreescribir onClick() y comentar / eliminar super.onClick() hace que SwitchPreference NO llame a callChangeListener(Object newValue) . Ahora puedes hacer clic en la preferencia y no pasa nada, no hasta que quieras. (Un error que se produciría de lo contrario era tener múltiples llamadas a onPreferenceChange en el fragmento)


¡Ahora! Para hacer que las cosas sucedan: Aquí está la estructura que he utilizado.

  • Crear una SettingsActivity
    • En él asegúrese de buscar las preferencias, recursos, etc
  • onCreate() en tu Actividad – onCreate() un PreferenceFragment
    • Esto debe ser una clase personalizada que extienda el PreferenceFragment , vea cómo aquí: PreferenceFragment
  • En su Fragmento personalizado, consiga su preferencia personalizada. Puede utilizar findPreference("custom_switch_key") .

    • Agregue un OnPreferenceChangeListener en la preferencia
    • Personalmente, hago que mi fragmento implemente el oyente y lo pase como argumento.
    • La declaración de devolución es importante. Esto es lo que hace que el cambio real en el interruptor. Si devuelve true, el cambio cambiará a newValue. Si devuelve un error, no lo hará. Si utiliza return false; Puede cambiar el valor con setChecked (true | false) en la preferencia de switch.
  • Cuando se implementa onPreferenceChange(Preference preference, Object newValue) , puede agregar cualquier funcionalidad que desee presionando el control deslizante solamente

  • La funcionalidad de hacer clic en la preferencia se puede hacer de tres maneras:
    • Implementar el onClick() más adelante en la clase personalizada SwitchPreference
    • Implementar el método onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) en el fragmento
    • Implementar un onPreferenceClickListener como lo hizo para el ChangeListener.

Lo siento si este es un mensaje largo. Es mi primera y he pasado por tantas stackoverflow-páginas sobre esto y nadie era preciso, sólo quería hacerlo bien;)

Pienso que usted está preguntando sobre una característica que no existe.

Sin embargo, como la actividad de preferencia utiliza un listView, puede utilizar algunos trucos para personalizarlo y manejarlo como desee.

Aquí hay un post que he hecho sobre la personalización, basado en este sitio web . Lo que he preguntado allí es cómo agregar un listView, pero no sabía que una actividad de la preferencia utiliza realmente un listview.

Después de buscar horas más me encontré con un par de mensajes que serán útiles para otros en esta situación.

Esta fue la solución que opté por dado mi problema: ¿Cómo puedo crear una preferencia con un EditTextPreference y un Togglebutton?

Es una respuesta muy detallada y es muy útil para entender las preferencias.

El otro post que encontré fue éste: http://xgouchet.fr/android/index.php?article4/master-on-off-preferences-with-ice-cream-sandwich

Le dará prácticamente la misma mirada y sensación que el anterior, pero requiere más trabajo y debido a mis requisitos no trabajaría para mí.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.