¿Cómo abrir o simular un clic en una preferencia de Android, creada con XML, programáticamente?

Tengo una aplicación de Android con preferencias declaradas en XML, cargadas con addPreferencesFromResource . El usuario puede abrir preferencias, hacer clic en cada elemento y editarlos, todo funciona.

Una preferencia que tengo es:

   

¿Cómo puedo mostrar el diálogo de preferencias a un usuario automáticamente (sin la necesidad de que el usuario vaya a la pantalla de preferencias y haga clic en él?).

Intenté ( (android.preference.DialogPreference) prefMgr.findPreference( "abc" )).showDialog(null) , pero dice que es un método protegido …? Lo llamé desde mi actividad principal (que es una actividad de PreferenceActivity ), es por eso que obviamente no puede funcionar. Pero, ¿de qué otra manera?

EDITAR

Acabo de encontrar dos hilos ( 1 y 2 ) con la idea de utilizar findViewById para acceder a la preferencia, pero sin éxito. Siempre devuelve null (también para mí).

Parece que realmente no hay posibilidad de hacer esto desde el código.

Podría haber extendido ListPreference para crear su diálogo, luego incluyó su propio método público que llama al método showDialog protegido de ListPreference. Algo como:

 public void show() { showDialog(null); } 

De esta forma, no se encontrará con el problema de que getOrder () no funcione cuando hay grupos de preferencias, ya que varias personas han señalado su respuesta en los comentarios.

Esto se puede hacer con cualquier tipo de preferencia que tenga un método protegido showDialog.

¡Vea la nueva respuesta aceptada para un enfoque mucho más limpio! Esto estaba funcionando, pero no era la manera más clara de hacerlo.


Maldita sea, me dio varias horas, pero finalmente funciona.

La solución es la llamada public void onItemClick (...) . Se necesitan varios argumentos, y tal como lo señala esta pregunta, se puede usar para simular un clic de acuerdo con el índice del elemento al que desea llamar.

Mi problema es que el elemento que quiero llamar está profundamente nested en una estructura XML. Pero la solución es muy sencilla: agregue una key a PreferenceScreen el elemento que desea abrir está en:

    

Y usted puede simplemente lo siguiente:

 // the preference screen your item is in must be known PreferenceScreen screen = (PreferenceScreen) findPreference("pref_key"); // the position of your item inside the preference screen above int pos = findPreference("abc").getOrder(); // simulate a click / call it!! screen.onItemClick( null, null, pos, 0 ); 

¡Y aparece el diálogo!

Sería bueno tener PreferenceScreen en la Preference (para que no tenga que saber dónde está su Preference ), porque mover la preferencia / cambiar el XML podría romper el diálogo automático en silencio y podría no notarse (si no se prueba) )

Para esto, escribí una función que buscará en todas las preferencias y devolverá la PreferenceScreen prefiera, ¡así que no necesita tener su tecla PreferenceScreen!

 private PreferenceScreen findPreferenceScreenForPreference( String key, PreferenceScreen screen ) { if( screen == null ) { screen = getPreferenceScreen(); } PreferenceScreen result = null; android.widget.Adapter ada = screen.getRootAdapter(); for( int i = 0; i < ada.getCount(); i++ ) { String prefKey = ((Preference)ada.getItem(i)).getKey(); if( prefKey != null && prefKey.equals( key ) ) { return screen; } if( ada.getItem(i).getClass().equals(android.preference.PreferenceScreen.class) ) { result = findPreferenceScreenForPreference( key, (PreferenceScreen) ada.getItem(i) ); if( result != null ) { return result; } } } return null; } private void openPreference( String key ) { PreferenceScreen screen = findPreferenceScreenForPreference( key, null ); if( screen != null ) { screen.onItemClick(null, null, findPreference(key).getOrder(), 0); } } // With this, you can call your `Preference` like this from code, you do // not even have to give your PreferenceScreen a key! openPreference( "abc" ); 
  PreferenceScreen preferenceScreen = (PreferenceScreen) findPreference("pref_key"); final ListAdapter listAdapter = preferenceScreen.getRootAdapter(); EditTextPreference editPreference = (EditTextPreference) findPreference("set_password_preference"); final int itemsCount = listAdapter.getCount(); int itemNumber; for (itemNumber = 0; itemNumber < itemsCount; ++itemNumber) { if (listAdapter.getItem(itemNumber).equals(editPreference)) { preferenceScreen.onItemClick(null, null, itemNumber, 0); break; } } } } 

Mejorando la respuesta de deepak goel :

 private void openPreference(String key) { PreferenceScreen preferenceScreen = getPreferenceScreen(); final ListAdapter listAdapter = preferenceScreen.getRootAdapter(); final int itemsCount = listAdapter.getCount(); int itemNumber; for (itemNumber = 0; itemNumber < itemsCount; ++itemNumber) { if (listAdapter.getItem(itemNumber).equals(findPreference(key))) { preferenceScreen.onItemClick(null, null, itemNumber, 0); break; } } } 

Si usa la biblioteca de soporte, puede abrir un cuadro de diálogo fácilmente con PreferenceManager.showDialog (Preferencia) .

En su PreferenceFragmentCompat:

 getPreferenceManager().showDialog(findPreference("pref_name")); 

Tenga en cuenta que el paquete de preferencias de soporte tiene muchos problemas: el estilo no material y se bloquea al rotar con un cuadro de diálogo abierto .

espera, puedes hacer algo como esto también

 Preference p=findPreference("settings_background_color"); p.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { int color=PreferenceManager.getDefaultSharedPreferences(ALifePatternsWallpaperSettings.this).getInt("settings_background_color", Color.BLACK); new ColorPickerDialog(ALifePatternsWallpaperSettings.this, ALifePatternsWallpaperSettings.this, "settings_background_color", color, Color.BLACK).show(); return true; } }); 

Hola amigos, prueba este código en funciona bien

 getPreferenceManager().findPreference("YOUR PREF_KEY").setOnPreferenceClickListener(new OnPreferenceClickListener() { public boolean onPreferenceClick(Preference preference) { //your code here return true; } });