La barra de herramientas está oculta en la ventana de preferencias anidadas

Utilizo PreferenceFragment en ActionBarActivity de la ActionBarActivity de soporte-v7.
En la Actividad Tengo Toolbar . Todo va bien, hasta que abra una PreferredScreen anidada.
En la pantalla abierta, la Toolbar está oculta.

Tal vez alguien conoce una solución para este problema?

Preferencias xml-file:

 <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > <PreferenceCategory android:title="Main category" > <EditTextPreference android:defaultValue="defaultValue" android:key="key_global_setting" android:title="Global title" /> </PreferenceCategory> <PreferenceCategory android:title="Nested screens" > <PreferenceScreen android:persistent="false" android:title="@string/settings_facility_title" > <CheckBoxPreference android:defaultValue="false" android:key="nested_screen_1_1" android:title="Nested screen 1.1 check box" /> <CheckBoxPreference android:defaultValue="true" android:key="nested_screen_1_2" android:title="Nested screen 1.2 check box" /> </PreferenceScreen> <PreferenceScreen android:persistent="false" android:title="@string/settings_menu_screen_title" > <CheckBoxPreference android:defaultValue="true" android:key="nested_screen2" android:title="Nested screen 2 check box" /> </PreferenceScreen> </PreferenceCategory> </PreferenceScreen> 

Disposición de la actividad:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".SettingsScreen" > <android.support.v7.widget.Toolbar android:id="@+id/toolbar" style="@style/Toolbar" /> <FrameLayout android:id="@+id/contentSettings" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> 

Encontré la solución por mi cuenta. Utilicé un pequeño work-around de todos estos anidados PreferenceScreen's . Simplemente hice una separación a diferentes archivos de xml-preference , creé un Fragment adicional que extiende el archivo PreferenceFragment y allí muestro una pantalla de preferencia anidada apropiada.
Tal vez alguien lo encontró útil.

Github fuentes enlace.

Algunos ejemplos de código a continuación:

Main_preferences.xml

 <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > <PreferenceCategory android:title="Main category" > <EditTextPreference android:defaultValue="defaultValue" android:key="key_global_setting" android:title="Global title" /> </PreferenceCategory> <PreferenceCategory android:title="Nested screens" > <Preference android:key="NESTED_KEY1" android:persistent="false" android:title="Nested screen #1" /> <Preference android:key="NESTED_KEY2" android:persistent="false" android:title="Nested screen #2" /> </PreferenceCategory> </PreferenceScreen> 

Nested_screen1_preferences.xml

 <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="Nested screen #1" > <CheckBoxPreference android:defaultValue="false" android:key="nested_screen_1_1" android:title="Nested screen 1.1 check box" /> <CheckBoxPreference android:defaultValue="true" android:key="nested_screen_1_2" android:title="Nested screen 1.2 check box" /> </PreferenceScreen> 

Nested_screen2_preferences.xml

 <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="Nested screen #2"> <CheckBoxPreference android:defaultValue="true" android:key="nested_screen2" android:title="Nested screen 2 check box" /> </PreferenceScreen> 

SettingsActivity.java

 public class SettingsActivity extends ActionBarActivity implements MyPreferenceFragment.Callback { private static final String TAG_NESTED = "TAG_NESTED"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); if (toolbar != null) { setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); } if (savedInstanceState == null) { getFragmentManager().beginTransaction() .add(R.id.contentSettings, new MyPreferenceFragment()) .commit(); } } @Override public void onBackPressed() { // this if statement is necessary to navigate through nested and main fragments if (getFragmentManager().getBackStackEntryCount() == 0) { super.onBackPressed(); } else { getFragmentManager().popBackStack(); } } @Override public void onNestedPreferenceSelected(int key) { getFragmentManager().beginTransaction().replace(R.id.contentSettings, NestedPreferenceFragment.newInstance(key), TAG_NESTED).addToBackStack(TAG_NESTED).commit(); } } 

MyPreferenceFragment.java

 // The main preference fragment class public class MyPreferenceFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener { private Callback mCallback; private static final String KEY_1 = "NESTED_KEY1"; private static final String KEY_2 = "NESTED_KEY2"; @Override public void onAttach(Activity activity) { super.onAttach(activity); if (activity instanceof Callback) { mCallback = (Callback) activity; } else { throw new IllegalStateException("Owner must implement Callback interface"); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Load the preferences from an XML resource addPreferencesFromResource(R.xml.main_preferences); // add listeners for non-default actions Preference preference = findPreference(KEY_1); preference.setOnPreferenceClickListener(this); preference = findPreference(KEY_2); preference.setOnPreferenceClickListener(this); } @Override public boolean onPreferenceClick(Preference preference) { // here you should use the same keys as you used in the xml-file if (preference.getKey().equals(KEY_1)) { mCallback.onNestedPreferenceSelected(NestedPreferenceFragment.NESTED_SCREEN_1_KEY); } if (preference.getKey().equals(KEY_2)) { mCallback.onNestedPreferenceSelected(NestedPreferenceFragment.NESTED_SCREEN_2_KEY); } return false; } public interface Callback { public void onNestedPreferenceSelected(int key); } } 

NestedPreferencesFragment.java

 public class NestedPreferenceFragment extends PreferenceFragment { public static final int NESTED_SCREEN_1_KEY = 1; public static final int NESTED_SCREEN_2_KEY = 2; private static final String TAG_KEY = "NESTED_KEY"; public static NestedPreferenceFragment newInstance(int key) { NestedPreferenceFragment fragment = new NestedPreferenceFragment(); // supply arguments to bundle. Bundle args = new Bundle(); args.putInt(TAG_KEY, key); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); checkPreferenceResource(); } private void checkPreferenceResource() { int key = getArguments().getInt(TAG_KEY); // Load the preferences from an XML resource switch (key) { case NESTED_SCREEN_1_KEY: addPreferencesFromResource(R.xml.nested_screen1_preferences); break; case NESTED_SCREEN_2_KEY: addPreferencesFromResource(R.xml.nested_screen2_preferences); break; default: break; } } } 

Aquí viene mi solución, que se inspira en la respuesta original, pero no tan complicado. Tal vez ayude a alguien …

layout/settings.xml :

  <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > <include android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" layout="@layout/toolbar" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/content" android:layout_below="@+id/toolbar"/> </RelativeLayout> 

Clases:

 public class SettingsActivity extends ActionBarActivity { @Override protected void onCreate( Bundle savedInstanceState ) { setContentView( R.layout.settings ); super.onCreate( savedInstanceState ); initializeSupportActionBar(); getFragmentManager().beginTransaction().replace( R.id.content, new MainFragment() ).commit(); } @Override public void onBackPressed() { if( !getFragmentManager().popBackStackImmediate() ) super.onBackPressed(); } } public class MainFragment extends PreferenceFragment { public MainFragment() {} @Override public void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); addPreferencesFromResource( R.xml.pref_main ); // "nested" is the <Preference android:key="nested" android:persistent="false"/>` findPreference( "nested" ).setOnPreferenceClickListener( new OnPreferenceClickListener() { @Override public boolean onPreferenceClick( Preference preference ) { getFragmentManager().beginTransaction().replace( R.id.content, new NestedFragment() ).addToBackStack( NestedFragment.class.getSimpleName() ).commit(); return true; } } ); } public class NestedFragment extends PreferenceFragment { ... } 

Lo probé en 4.3 y 5.0.2 y no se aplica ninguna limitación en los niveles de anidación

En mi solución solo necesitas una AppCompatActivity y un PreferenceFragement , pero varios archivos XML, cada uno con sólo un nivel de PreferenceScreens .

Lista de archivos XML

  • Nivel superior PreferenceScreen
  • Segundo nivel PreferenceScreen 0
  • Segundo nivel PreferenceScreen 1
  • Segundo nivel PreferenceScreen 2

Este código es para un sub-nivel (por simplicidad y para obtener la idea), pero se puede extender fácilmente para tener subniveles arbitrarios de PreferenceScreens .

SettingsFragment.java

 public class SettingsFragment extends PreferenceFragment { private int xmlId; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); xmlId = R.xml.preferences; addPreferencesFromResource(xmlId); } public void changePrefScreen(int xmlId, int titleId) { this.xmlId = xmlId; ((AppCompatActivity)getActivity()).getSupportActionBar().setTitle(getActivity().getResources().getString(titleId)); getPreferenceScreen().removeAll(); addPreferencesFromResource(xmlId); } // will be called by SettingsActivity (Host Activity) public void onUpButton() { if(xmlId == R.xml.preferences) // in top-level { // Switch to MainActivity Intent intent = new Intent(getActivity(), MainActivity.class); startActivity(intent); } else // in sub-level { changePrefScreen(R.xml.preferences, R.string.settings); } } @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { String key = preference.getKey(); // // Top level PreferenceScreen // if(key.equals("top_key_0")) { changePrefScreen(R.xml.download_preference_screen, R.string.download_database); // descend into second level } // ... // // Second level PreferenceScreens // if (key.equals("second_level_key_0")) { // do something... } // ... } 

SettingsActivity.java

 public class SettingsActivity extends AppCompatActivity { SettingsFragment settingsFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); settingsFragment = new SettingsFragment(); // Display the fragment as the main content. getFragmentManager().beginTransaction() .replace(android.R.id.content, settingsFragment) .commit(); } // // Handle what happens on up button // @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: settingsFragment.onUpButton(); return true; } return true; } // ... } 

Técnicamente debe funcionar para todas las versiones de Android para las que el PreferenceFragment está disponible.

Como el problema proviene de la parte en la que todavía está en la misma actividad / fragmento y la pantalla de prefijo anidado es sólo un diálogo, puede hacer lo siguiente:

  • Puede establecer un marcador de clics de preferencias
  • Obtenga la vista raíz desde el diálogo: (PreferenceScreen)preference).getDialog().getWindow() .getDecorView().getRootView());

  • Recursivamente buscar hasta encontrar una vista de topo (hay uno, por desgracia no sé el android.R.id.xxxxx ) y establecer qué diseño que necesita como título que se verá como la barra de herramientas (Puede inflar barra de herramientas):

     private Toolbar toolbar; public void findViewStub(ViewGroup viewGroup) { int childCount = viewGroup.getChildCount(); for (int i = 0; i < childCount; i++) { View childView = viewGroup.getChildAt(i); if( childView instanceof ViewStub){ ((ViewStub)childView).setLayoutResource(R.layout.your_title_layout); toolbar = ((ViewStub)childView).inflate(); } if (childView instanceof ViewGroup) { findViewStub((ViewGroup) childView); } } } toolbar.setNavigationIcon(); toolbar.setNavigationOnClickListener(); toolbar.setTitle(); 
  • En el diseño sólo se puede colocar una barra de herramientas. Y establecer el icono de nuevo. Regístrese para hacer clic en él y teniendo referencia al fragmento, al hacer clic en puede descartar el diálogo. Has definido el título y el etc.

  • El menú de la barra de herramientas no funciona con ViewPager
  • Barra de herramientas de Android llena toda la pantalla
  • Desapareciendo el título de la barra de herramientas
  • Android TabLayout no se alineará a la derecha una vez Se reanuda la actividad
  • Cómo puedo colocar el menú de desbordamiento debajo de la barra de herramientas en lugar del menú de desbordamiento para superponer la barra de aplicaciones
  • Android "más suave" ocultación de la barra de herramientas al desplazarse
  • Barra de herramientas en DialogFragment
  • Android: Barra de herramientas Color del texto
  • Superposición de contenido por encima de AppBarLayout utilizando nuevo diseño de material
  • La barra de herramientas de Android se vuelve translúcida al navegar hacia atrás
  • Pantalla completa Con la barra de herramientas y edittext en la parte inferior de Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.