PreferenceInternet no se abre con PreferenceFragmentCompat

Mi PreferenceScreen interno de PreferenceFragmentCompat no está mostrando, o parece ignorar los eventos de tapping.

He creado MyPreferenceFragment que extends PreferenceFragmentCompat

 public class MyPreferenceFragment extends PreferenceFragmentCompat { @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { addPreferencesFromResource(R.xml.preferences); } } 

entonces cambié mi tema en styles.xml como

 <style name="AppTheme" parent="@style/Theme.AppCompat.Light"> <item name="preferenceTheme">@style/PreferenceThemeOverlay</item> </style> 

Y finalmente crear mi archivo preferences.xml como

 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <CheckBoxPreference android:title="Check Me"/> <PreferenceScreen android:title="My Screen"> <!-- This is not opening --> <EditTextPreference android:title="Edit text" /> </PreferenceScreen> </PreferenceScreen> 

En el build.gradle he añadido ambos:

 compile 'com.android.support:appcompat-v7:23.0.1' compile 'com.android.support:preference-v7:23.0.1' 

código de la actividad

 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } } 

activity_main.xml

 <fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment" android:name="com.mando.preferenceapp.MyPreferenceFragment" android:layout_width="match_parent" android:layout_height="match_parent" /> 

Prueba del código anterior No puedo abrir / entrar en la pantalla de preferencias. ¿Me estoy perdiendo de algo? ¿Por qué esto no funciona?

Después de pasar muchas horas con intentos, buscando y agradecidamente con alguna ayuda de los creadores de la biblioteca de apoyo. He conseguido que funcione.

Paso 1. Activity

 public class MyActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState == null) { // Create the fragment only when the activity is created for the first time. // ie. not after orientation changes Fragment fragment = getSupportFragmentManager().findFragmentByTag(MyPreferenceFragment.FRAGMENT_TAG); if (fragment == null) { fragment = new MyPreferenceFragment(); } FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.fragment_container, fragment, MyPreferenceFragment.FRAGMENT_TAG); ft.commit(); } } @Override public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat, PreferenceScreen preferenceScreen) { FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); MyPreferenceFragment fragment = new MyPreferenceFragment(); Bundle args = new Bundle(); args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.getKey()); fragment.setArguments(args); ft.replace(R.id.fragment_container, fragment, preferenceScreen.getKey()); ft.addToBackStack(preferenceScreen.getKey()); ft.commit(); return true; } } 

Consejos.

  • No agregue el fragmento por xml , tendrá fallos en los cambios de orientación.
  • Manejar las recreaciones de actividad / fragmento agregar en onCreate para evitar perder su fragmento cuando está dentro de una pantalla de preferencias.
  • La actividad de host del fragmento debe implementar el PreferenceFragmentCompat.OnPreferenceStartScreenCallback y volver a crear fragmentos de la misma instancia.

Paso 2. PreferenceFragment

 public class MyPreferenceFragment extends PreferenceFragmentCompat { public static final String FRAGMENT_TAG = "my_preference_fragment"; public MyPreferenceFragment() { } @Override public void onCreatePreferences(Bundle bundle, String rootKey) { setPreferencesFromResource(R.xml.preferences, rootKey); } } 

Consejos.

  • Utilice el método setPreferencesFromResource y aproveche la rootKey de cada pantalla. De esta manera su código se reutilizará correctamente.
  • Tenga en cuenta que si tiene código como findPreference en su fragmento debe tener controles null como cuando estaba en pantallas internas esto no le dará nada.

Lo que falta ahora es la implementación de la flecha hacia atrás en la barra de acción (acción de casa) pero esto nunca funciona por sí mismo 😉

También he creado una aplicación demo que envuelve todo este código que puedes encontrar en github .

Lo hice de manera ligeramente diferente, estoy lanzando una nueva actividad para cada pantalla. Esto parece requerir menos hacks: no hay necesidad de meterse con el intercambio de fragmentos y colores de fondo. Usted también consigue animación de cambio de actividad como un bono!

 public class PreferencesActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback { final static private String KEY = "key"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.preferences); setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) actionBar.setDisplayHomeAsUpEnabled(true); if (savedInstanceState != null) return; Fragment p = new PreferencesFragment(); String key = getIntent().getStringExtra(KEY); if (key != null) { Bundle args = new Bundle(); args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, key); p.setArguments(args); } getSupportFragmentManager().beginTransaction() .add(R.id.preferences, p, null) .commit(); } @Override public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat, PreferenceScreen preferenceScreen) { Intent intent = new Intent(PreferencesActivity.this, PreferencesActivity.class); intent.putExtra(KEY, preferenceScreen.getKey()); startActivity(intent); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { onBackPressed(); return true; } return super.onOptionsItemSelected(item); } public static class PreferencesFragment extends PreferenceFragmentCompat implements ... { private static final String FRAGMENT_DIALOG_TAG = "android.support.v7.preference.PreferenceFragment.DIALOG"; private String key; @Override public void onCreatePreferences(Bundle bundle, String key) { setPreferencesFromResource(R.xml.preferences, this.key = key); } // this only sets the title of the action bar @Override public void onActivityCreated(Bundle savedInstanceState) { ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); if (actionBar != null) actionBar.setTitle((key == null) ? "Settings" : findPreference(key).getTitle()); super.onActivityCreated(savedInstanceState); } } } 

xml:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="0dp" android:orientation="vertical" android:padding="0dp" android:id="@+id/preferences"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" /> <!-- preference fragment will be inserted here programmatically --> </LinearLayout> 

Basado en la solución @squirrel Intent, lo hice funcionar de esta manera. Requiere aún menos hacking.
Actividad:

 import android.support.v7.app.AppCompatActivity; public class SettingsActivity extends AppCompatActivity { public static final String TARGET_SETTING_PAGE = "target"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SettingsFragment settingsFragment = new SettingsFragment(); Intent intent = getIntent(); if (intent != null) { String rootKey = intent.getStringExtra(TARGET_SETTING_PAGE); if (rootKey != null) { settingsFragment.setArguments(Bundler.single(TARGET_SETTING_PAGE, rootKey)); } } getFragmentManager().beginTransaction() .replace(android.R.id.content, settingsFragment) .commit(); } } 

Fragmento:

 import android.support.v14.preference.PreferenceFragment; public class SettingsFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle arguments = getArguments(); if (arguments != null && arguments.getString(TARGET_SETTING_PAGE) != null) { setPreferencesFromResource(R.xml.preferences, arguments.getString(TARGET_SETTING_PAGE)); } else { addPreferencesFromResource(R.xml.preferences); } } @Override public void onNavigateToScreen(PreferenceScreen preferenceScreen) { Intent intent = new Intent(getActivity(), SettingsActivity.class) .putExtra(TARGET_SETTING_PAGE, preferenceScreen.getKey()); startActivity(intent); super.onNavigateToScreen(preferenceScreen); } } 

Es triste que necesites tantos hacks en las librerías appcompat de soporte para algo que funcione perfectamente out-of-the-box en android estándar.

  • ¿Cómo puedo crear preferencias personalizadas usando la biblioteca android.support.v7.preference?
  • Indeterminado Horizontal ProgressBar ABAJO ActionBar usando AppCompat?
  • CardView inserta la línea oscura en la parte inferior
  • Diferencia entre ActionBarActivity y Fragment Activity
  • Mientras uso la biblioteca de soporte técnico estoy recibiendo un error que el atributo "" ya ha sido definido en android
  • Android DrawerLayout.setDrawerLockMode () no funciona
  • AppCompat v7: ¿Debo usar Framework FragmentManager o SupportFragmentManager?
  • AppCompat y EditText subrayado diferente en diferentes API
  • ¿Cómo crear la barra de herramientas con el botón personalizado a la izquierda?
  • Android Studio - Valores de error de compilación de Appcompat-v23 / styles_bases.xml
  • ViewPager en CoordinatorLayout se contrae inesperadamente
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.