tutorial studio example developer configuracion archivos archivo android android-preferences android-support-library android-toolbar preferencefragment

android - studio - La barra de herramientas está oculta en PreferenceScreen anidado



preferencescreen android tutorial (4)

Aquí viene mi solución, que está inspirada en la respuesta original pero no tan complicada. 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 anidamiento

Uso PreferenceFragment en ActionBarActivity de la biblioteca support-v7.
En la actividad tengo Toolbar . Todo va bien, hasta que abro una PreferenceScreen anidada.
En la pantalla abierta la Toolbar está oculta.

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

Preferencias de archivo 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" > <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>

Diseño 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>


Como el problema proviene de la parte en la que aún se encuentra en la misma actividad / fragmento y la pantalla de preferencias anidada es solo un cuadro de diálogo, puede hacer lo siguiente:

  • Puede establecer preferencia escucha clic
  • Obtenga la vista raíz desde el cuadro de diálogo: (PreferenceScreen)preference).getDialog().getWindow() .getDecorView().getRootView());

  • Busque de forma recursiva hasta encontrar una vista de código auxiliar (hay una, desafortunadamente no conozco android.R.id.xxxxx ) y establezca qué diseño necesita como título, que se verá como la barra de herramientas (puede inflar la 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 solo se puede poner una barra de herramientas. Y establece el icono de volver. Regístrese para hacer clic en él y haciendo referencia al fragmento, al hacer clic en este botón puede cerrar el diálogo. Has puesto título y etc.


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

Lista de archivos XML

  • PreferenceScreen de nivel superior
  • PreferenceScreen 0 de segundo nivel
  • PreferenceScreen 1 de segundo nivel
  • PreferenceScreen 2 de segundo nivel
  • ...

Este código es para un subnivel (por simplicidad y para tener una idea), pero puede extenderlo 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... } // ... }

ConfiguraciónActividad.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 debería funcionar para todas las versiones de Android para las que está disponible PreferenceFragment .


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

Github fuentes de 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>

ConfiguraciónActividad.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; } } }