Crear una pantalla de preferencias con la barra de herramientas de soporte (v21)

Estaba teniendo problemas para usar la nueva barra de herramientas Material Design en la biblioteca de soporte en una pantalla de preferencias.

Tengo un archivo settings.xml de la siguiente manera:

     

Las cadenas están definidas en otra parte.

Encuentre el GitHub Repo: aquí


Un poco tarde para la fiesta, pero esta es mi solución que estoy usando para trabajar con PreferenceActivity :

settings_toolbar.xml :

 < ?xml version="1.0" encoding="utf-8"?>  

SettingsActivity.java :

 public class SettingsActivity extends PreferenceActivity { @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent(); Toolbar bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false); root.addView(bar, 0); // insert at top bar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); } } 

Result :

ejemplo


ACTUALIZACIÓN (Gingerbread Compatibility):

Según los comentarios, los dispositivos Gingerbread devuelven NullPointerException en esta línea:

 LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent(); 

FIJAR:

SettingsActivity.java :

 public class SettingsActivity extends PreferenceActivity { @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); Toolbar bar; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { LinearLayout root = (LinearLayout) findViewById(android.R.id.list).getParent().getParent().getParent(); bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false); root.addView(bar, 0); // insert at top } else { ViewGroup root = (ViewGroup) findViewById(android.R.id.content); ListView content = (ListView) root.getChildAt(0); root.removeAllViews(); bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false); int height; TypedValue tv = new TypedValue(); if (getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) { height = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics()); }else{ height = bar.getHeight(); } content.setPadding(0, height, 0, 0); root.addView(content); root.addView(bar); } bar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); } } 

Cualquier problema con lo anterior, hágamelo saber!


ACTUALIZACIÓN 2: TINTING WORKAROUND

Como se señala en muchas notas de desarrollo, PreferenceActivity no es compatible con el tinte de elementos, sin embargo, al utilizar algunas clases internas, PUEDE lograrlo. Eso es hasta que se eliminen estas clases. (Funciona con appCompat support-v7 v21.0.3).

Agregue las siguientes importaciones:

 import android.support.v7.internal.widget.TintCheckBox; import android.support.v7.internal.widget.TintCheckedTextView; import android.support.v7.internal.widget.TintEditText; import android.support.v7.internal.widget.TintRadioButton; import android.support.v7.internal.widget.TintSpinner; 

Luego, anule el método onCreateView :

 @Override public View onCreateView(String name, Context context, AttributeSet attrs) { // Allow super to try and create a view first final View result = super.onCreateView(name, context, attrs); if (result != null) { return result; } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { // If we're running pre-L, we need to 'inject' our tint aware Views in place of the // standard framework versions switch (name) { case "EditText": return new TintEditText(this, attrs); case "Spinner": return new TintSpinner(this, attrs); case "CheckBox": return new TintCheckBox(this, attrs); case "RadioButton": return new TintRadioButton(this, attrs); case "CheckedTextView": return new TintCheckedTextView(this, attrs); } } return null; } 

Result:

ejemplo 2


AppCompat 22.1

AppCompat 22.1 introdujo nuevos elementos tintados, lo que significa que ya no es necesario utilizar las clases internas para lograr el mismo efecto que la última actualización. En su lugar, siga esto (sigue anulando en onCreateView ):

 @Override public View onCreateView(String name, Context context, AttributeSet attrs) { // Allow super to try and create a view first final View result = super.onCreateView(name, context, attrs); if (result != null) { return result; } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { // If we're running pre-L, we need to 'inject' our tint aware Views in place of the // standard framework versions switch (name) { case "EditText": return new AppCompatEditText(this, attrs); case "Spinner": return new AppCompatSpinner(this, attrs); case "CheckBox": return new AppCompatCheckBox(this, attrs); case "RadioButton": return new AppCompatRadioButton(this, attrs); case "CheckedTextView": return new AppCompatCheckedTextView(this, attrs); } } return null; } 

PANTALLAS DE PREFERENCIA ANIDAS

Mucha gente tiene problemas para incluir la barra de herramientas en una

anidada; sin embargo, ¡he encontrado una solución! - ¡Después de mucho ensayo y error!

Agregue lo siguiente a su SettingsActivity :

 @SuppressWarnings("deprecation") @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { super.onPreferenceTreeClick(preferenceScreen, preference); // If the user has clicked on a preference screen, set up the screen if (preference instanceof PreferenceScreen) { setUpNestedScreen((PreferenceScreen) preference); } return false; } public void setUpNestedScreen(PreferenceScreen preferenceScreen) { final Dialog dialog = preferenceScreen.getDialog(); Toolbar bar; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { LinearLayout root = (LinearLayout) dialog.findViewById(android.R.id.list).getParent(); bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false); root.addView(bar, 0); // insert at top } else { ViewGroup root = (ViewGroup) dialog.findViewById(android.R.id.content); ListView content = (ListView) root.getChildAt(0); root.removeAllViews(); bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false); int height; TypedValue tv = new TypedValue(); if (getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) { height = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics()); }else{ height = bar.getHeight(); } content.setPadding(0, height, 0, 0); root.addView(content); root.addView(bar); } bar.setTitle(preferenceScreen.getTitle()); bar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); } 

El motivo por el que PreferenceScreen es tan molesto es porque se basan en un cuadro de diálogo contenedor, por lo que debemos capturar el diseño del cuadro de diálogo para agregarle la barra de herramientas.


Barra de herramientas Shadow

Por diseño, la importación de la Toolbar no permite la elevación y el sombreado en dispositivos anteriores a v21, por lo que si desea tener elevación en su Toolbar , debe envolverlo en un AppBarLayout :

settings_toolbar.xml :

    

Sin olvidarse de agregar agregar la biblioteca Design Support como una dependencia en el archivo build.gradle :

 compile 'com.android.support:support-v4:22.2.0' compile 'com.android.support:appcompat-v7:22.2.0' compile 'com.android.support:design:22.2.0' 

Android 6.0

Investigué el problema superpuesto y no puedo reproducir el problema.

El código completo en uso como arriba produce lo siguiente:

enter image description here

Si me falta algo, házmelo saber a través de este repository e investigaré.

Puede usar un PreferenceFragment , como una alternativa a PreferenceActivity . Entonces, aquí está el ejemplo de la Activity envoltura:

 public class MyPreferenceActivity extends ActionBarActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.pref_with_actionbar); android.support.v7.widget.Toolbar toolbar = (android.support.v7.widget.Toolbar) findViewById(uk.japplications.jcommon.R.id.toolbar); setSupportActionBar(toolbar); getFragmentManager().beginTransaction().replace(R.id.content_frame, new MyPreferenceFragment()).commit(); } } 

Y aquí está el archivo de diseño (pref_with_actionbar):

     

Y finalmente el PreferenceFragment :

 public static class MyPreferenceFragment extends PreferenceFragment{ @Override public void onCreate(final Bundle savedInstanceState){ super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.settings); } } 

Espero que esto ayude a alguien.

Completamente nueva actualización.

Con algo de experimentación, parece que encontré la solución funcional AppCompat 22.1+ para pantallas de preferencias anidadas.

En primer lugar, como se menciona en muchas respuestas (incluida una aquí), deberá usar el nuevo AppCompatDelegate . Utilice el archivo AppCompatPreferenceActivity.java de las demos de soporte ( https://android.googlesource.com/platform/development/+/58bf5b99e6132332afb8b44b4c8cedf5756ad464/samples/Support7Demos/src/com/example/android/supportv7/app/AppCompatPreferenceActivity.java ) y simplemente extender desde allí, o copiar las funciones relevantes en su propia PreferenceActivity . Voy a mostrar el primer acercamiento aquí:

 public class SettingsActivity extends AppCompatPreferenceActivity { @Override public void onBuildHeaders(List
target) { loadHeadersFromResource(R.xml.settings, target); setContentView(R.layout.settings_page); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); ActionBar bar = getSupportActionBar(); bar.setHomeButtonEnabled(true); bar.setDisplayHomeAsUpEnabled(true); bar.setDisplayShowTitleEnabled(true); bar.setHomeAsUpIndicator(R.drawable.abc_ic_ab_back_mtrl_am_alpha); bar.setTitle(...); } @Override protected boolean isValidFragment(String fragmentName) { return SettingsFragment.class.getName().equals(fragmentName); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: onBackPressed(); break; } return super.onOptionsItemSelected(item); } }

El diseño que lo acompaña es bastante simple y habitual ( layout/settings_page.xml ):

     

Las preferencias mismas se definen como de costumbre ( xml/settings.xml ):

  
...

No hay diferencia real para las soluciones en la red hasta este punto. En realidad, puedes usar esto incluso si no tienes pantallas anidadas, ni encabezados, solo una pantalla.

Usamos un PreferenceFragment común para todas las páginas más profundas, diferenciadas por los parámetros extra en los encabezados. Cada página tendrá un XML separado con una PreferenceScreen común dentro ( xml/settings_page1.xml et al.). El fragmento usa el mismo diseño que la actividad, incluida la barra de herramientas.

 public class SettingsFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getActivity().setTheme(R.style...); if (getArguments() != null) { String page = getArguments().getString("page"); if (page != null) switch (page) { case "page1": addPreferencesFromResource(R.xml.settings_page1); break; case "page2": addPreferencesFromResource(R.xml.settings_page2); break; ... } } } @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View layout = inflater.inflate(R.layout.settings_page, container, false); if (layout != null) { AppCompatPreferenceActivity activity = (AppCompatPreferenceActivity) getActivity(); Toolbar toolbar = (Toolbar) layout.findViewById(R.id.toolbar); activity.setSupportActionBar(toolbar); ActionBar bar = activity.getSupportActionBar(); bar.setHomeButtonEnabled(true); bar.setDisplayHomeAsUpEnabled(true); bar.setDisplayShowTitleEnabled(true); bar.setHomeAsUpIndicator(R.drawable.abc_ic_ab_back_mtrl_am_alpha); bar.setTitle(getPreferenceScreen().getTitle()); } return layout; } @Override public void onResume() { super.onResume(); if (getView() != null) { View frame = (View) getView().getParent(); if (frame != null) frame.setPadding(0, 0, 0, 0); } } } 

Finalmente, un resumen rápido de cómo funciona esto realmente. El nuevo AppCompatDelegate nos permite usar cualquier actividad con las características de AppCompat, no solo aquellas que se extienden desde las actividades en realidad en AppCompat. Esto significa que podemos convertir la buena vieja PreferenceActivity en una nueva y agregar la barra de herramientas como de costumbre. A partir de ese momento, podemos apegarnos a las soluciones anteriores con respecto a pantallas y encabezados de preferencia, sin desviarnos de la documentación existente. Solo hay un punto importante: no use onCreate() en la actividad porque generará errores. Use onBuildHeaders() para todas las operaciones, como agregar la barra de herramientas.

La única diferencia real es, y eso es lo que hace que funcione con pantallas anidadas, es que puedes usar el mismo enfoque con los fragmentos. Puede usar onCreateView() la misma manera, inflando su propio diseño en lugar del sistema, agregando la barra de herramientas de la misma manera que en la actividad.

Si desea utilizar los PreferenceHeaders, puede usar el siguiente enfoque:

 import android.support.v7.widget.Toolbar; public class MyPreferenceActivity extends PreferenceActivity Toolbar mToolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ViewGroup root = (ViewGroup) findViewById(android.R.id.content); LinearLayout content = (LinearLayout) root.getChildAt(0); LinearLayout toolbarContainer = (LinearLayout) View.inflate(this, R.layout.activity_settings, null); root.removeAllViews(); toolbarContainer.addView(content); root.addView(toolbarContainer); mToolbar = (Toolbar) toolbarContainer.findViewById(R.id.toolbar); } @Override public void onBuildHeaders(List
target) { loadHeadersFromResource(R.xml.pref_headers, target); } // Other methods }

layout / activity_settings.xml

    

Puedes usar cualquier diseño que prefieras aquí, solo asegúrate de ajustarlo en el código Java también.

Y finalmente, su archivo con encabezados (xml / pref_headers.xml)

  

Con el lanzamiento de Android Support Library 22.1.0 y el nuevo AppCompatDelegate, aquí puede encontrar una buena muestra de una implementación de PreferenceActivity con soporte de materiales con compatibilidad hacia atrás.

Actualización También funciona en pantallas anidadas.

https://android.googlesource.com/platform/development/+/marshmallow-mr3-release/samples/Support7Demos/src/com/example/android/supportv7/app/AppCompatPreferenceActivity.java

Si bien las respuestas anteriores parecen complicadas, si quiere una solución de solución rápida para usar la Barra de herramientas con compatibilidad con API 7 y todo mientras amplía PreferenceActivity , recibí ayuda de este proyecto a continuación.

https://github.com/AndroidDeveloperLB/ActionBarPreferenceActivity

activity_settings.xml

      

SettingsActivity.java

 public class SettingsActivity extends PreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); addPreferencesFromResource(R.xml.preferences); toolbar.setClickable(true); toolbar.setNavigationIcon(getResIdFromAttribute(this, R.attr.homeAsUpIndicator)); toolbar.setTitle(R.string.menu_settings); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); } private static int getResIdFromAttribute(final Activity activity, final int attr) { if (attr == 0) { return 0; } final TypedValue typedvalueattr = new TypedValue(); activity.getTheme().resolveAttribute(attr, typedvalueattr, true); return typedvalueattr.resourceId; } } 

Yo también he estado buscando una solución para agregar la barra de herramientas de soporte v7 ( API 25 ) a AppCompatPreferenceActivity (que se crea automáticamente con AndroidStudio al agregar una Configuración de actividad). Después de leer varias soluciones y probar cada una de ellas, me costó conseguir que los ejemplos de Fragmentos de Preferencias generados también se mostraran con una barra de herramientas.

Una solución modificada que funcionaba de alguna manera era ” Gabor “.

Una de las advertencias que enfrenté fue ‘solo en los fogones de Bomberos’ una vez. Si enciende un dispositivo (como un teléfono) de lado, la vista se recrea y la actividad de preferencia se deja sin una barra de herramientas nuevamente, sin embargo, los fragmentos de preferencias retendrían los suyos.

Intenté usar ‘onPostCreate’ para llamar a ‘setContentView’, mientras esto funcionaba para recrear la barra de herramientas cuando la orientación cambiaba, PreferenceFragments se dejaba en blanco.

Lo que se me ocurre aprovecha casi todos los consejos y respuestas que pude leer sobre este tema. Espero que otros lo encuentren útil también.

Comenzaremos con Java

Primero en (generado) AppCompatPreferenceActivity.java Modifiqué ‘setSupportActionBar’ de esta manera:

 public void setSupportActionBar(@Nullable Toolbar toolbar) { getDelegate().setSupportActionBar(toolbar); ActionBar bar = getDelegate().getSupportActionBar(); bar.setHomeButtonEnabled(true); bar.setDisplayHomeAsUpEnabled(true); } 

En segundo lugar , creé una nueva clase llamada AppCompatPreferenceFragment.java (es un nombre actual no utilizado, ¡aunque puede no ser así!):

 abstract class AppCompatPreferenceFragment extends PreferenceFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.activity_settings, container, false); if (view != null) { Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar_settings); ((AppCompatPreferenceActivity) getActivity()).setSupportActionBar(toolbar); } return view; } @Override public void onResume() { super.onResume(); View frame = (View) getView().getParent(); if (frame != null) frame.setPadding(0, 0, 0, 0); } } 

Esta es la parte de la respuesta de Gabor que funcionó.

Por último , para obtener coherencia, debemos realizar algunos cambios en SettingsActivity.java :

 public class SettingsActivity extends AppCompatPreferenceActivity { boolean mAttachedFragment; @Override protected void onCreate(Bundle savedInstanceState) { mAttachedFragment = false; super.onCreate(savedInstanceState); } @Override @TargetApi(Build.VERSION_CODES.HONEYCOMB) public void onBuildHeaders(List
target) { loadHeadersFromResource(R.xml.pref_headers, target); } @Override public void onAttachFragment(Fragment fragment) { mAttachedFragment = true; super.onAttachFragment(fragment); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); //if we didn't attach a fragment, go ahead and apply the layout if (!mAttachedFragment) { setContentView(R.layout.activity_settings); setSupportActionBar((Toolbar)findViewById(R.id.toolbar_settings)); } } /** * This fragment shows general preferences only. It is used when the * activity is showing a two-pane settings UI. */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static class GeneralPreferenceFragment extends AppCompatPreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_general); setHasOptionsMenu(true); bindPreferenceSummaryToValue(findPreference("example_text")); bindPreferenceSummaryToValue(findPreference("example_list")); } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == android.R.id.home) { startActivity(new Intent(getActivity(), SettingsActivity.class)); return true; } return super.onOptionsItemSelected(item); } } }

Algunos códigos han quedado fuera de la actividad por brevedad. Los componentes clave aquí son ‘ onAttachedFragment ‘, ‘ onPostCreate ‘ y que ‘GeneralPreferenceFragment’ ahora amplía el ‘ AppCompatPreferenceFragment ‘ personalizado en lugar de PreferenceFragment.

Resumen del código : si hay un fragmento presente, el fragmento inyecta el nuevo diseño y llama a la función modificada ‘setSupportActionBar’. Si el fragmento no está presente, SettingsActivity inyecta el nuevo diseño en ‘onPostCreate’

Ahora a XML (muy simple):

activity_settings.xml :

 < ?xml version="1.0" encoding="utf-8"?>    

app_bar_settings.xml :

 < ?xml version="1.0" encoding="utf-8"?>       

content_settings.xml :

 < ?xml version="1.0" encoding="utf-8"?>    

Resultado final :

ConfiguraciónActividad

GeneralPreferenceFragment

Tengo una solución nueva (posiblemente más limpia), que usa AppCompatPreferenceActivity de las muestras de Support v7. Con este código en la mano, creé mi propio diseño que incluye una barra de herramientas:

 < ?xml version="1.0" encoding="utf-8"?>       

Luego, en mi AppCompatPreferenceActivity , modifiqué setContentView para crear un nuevo diseño y FrameLayout diseño proporcionado dentro de FrameLayout :

 @Override public void setContentView(@LayoutRes int layoutResID) { View view = getLayoutInflater().inflate(R.layout.toolbar, null); FrameLayout content = (FrameLayout) view.findViewById(R.id.content); getLayoutInflater().inflate(layoutResID, content, true); setContentView(view); } 

Luego, extiendo AppCompatPreferenceActivity , lo que me permite llamar a setSupportActionBar((Toolbar) findViewById(R.id.toolbar)) e inflar los elementos del menú en la barra de herramientas también. Todo mientras se mantienen los beneficios de una actividad de PreferenceActivity .

Vamos a mantenerlo simple y limpio aquí, sin romper ningún diseño incorporado

 import android.support.design.widget.AppBarLayout; import android.support.v4.app.NavUtils; import android.support.v7.widget.Toolbar; private void setupActionBar() { Toolbar toolbar = new Toolbar(this); AppBarLayout appBarLayout = new AppBarLayout(this); appBarLayout.addView(toolbar); final ViewGroup root = (ViewGroup) findViewById(android.R.id.content); final ViewGroup window = (ViewGroup) root.getChildAt(0); window.addView(appBarLayout, 0); setSupportActionBar(toolbar); // Show the Up button in the action bar. getSupportActionBar().setDisplayHomeAsUpEnabled(true); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); } 

Encontré esta solución simple mientras trabajaba en esto. Primero debemos crear un diseño para la actividad de configuración.

activity_settings.xml

     

Asegúrate de agregar una vista de lista con android:id="@android:id/list" , de lo contrario arrojará NullPointerException

El siguiente paso es agregar ( onCreate ) método onCreate en la actividad de configuración

Settings.java

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar); toolbar.setTitle(R.string.action_settings); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); } 

Asegúrese de importar android.suppoer.v7.widget.Toolbar . Esto debería funcionar prácticamente en todas las API superiores a 16 (Jelly Bean y superiores)

Me gustaría continuar la solución marcada de James Cross, ya que después de eso hay un problema de cerrar solo la pantalla anidada activa (PreferenceFragment) en el camino para no cerrar también la Configuración de la actividad.

Realmente funciona en todas las pantallas anidadas (así que no entiendo la solución de Gábor que intenté sin éxito, bueno, funciona hasta cierto punto pero es un desastre de barras de herramientas múltiples), porque cuando el usuario hace clic en una pantalla de sub preferencia , solo se cambia el fragmento (ver ) no la barra de herramientas que permanece siempre activa y visible, pero se debe implementar un comportamiento personalizado para cerrar cada fragmento en consecuencia.

En la clase principal SettingsActivity que amplía ActionBarActivity , se deben implementar los siguientes métodos. Tenga en cuenta que se setupActionBar() private setupActionBar() desde onCreate()

 private void setupActionBar() { Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar); //Toolbar will now take on default Action Bar characteristics setSupportActionBar(toolbar); getSupportActionBar().setHomeButtonEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: onBackPressed(); return true; } return super.onOptionsItemSelected(item); } @Override public void onBackPressed() { if (getFragmentManager().getBackStackEntryCount() > 0) { getFragmentManager().popBackStackImmediate(); //If the last fragment was removed then reset the title of main // fragment (if so the previous popBackStack made entries = 0). if (getFragmentManager().getBackStackEntryCount() == 0) { getSupportActionBar() .setTitle(R.string.action_settings_title); } } else { super.onBackPressed(); } } 

Para el título de la pantalla anidada elegida, debe obtener la referencia de su Barra de herramientas y establecer el título apropiado con la barra de herramientas. toolbar.setTitle(R.string.pref_title_general); (por ejemplo).

No es necesario implementar getSupportActionBar() en todos los PreferenceFragment ya que solo la vista del fragmento se cambia en cada commit, no en la barra de herramientas;

No es necesario crear una clase falsa ToolbarPreference para agregar en cada preference.xml (ver la respuesta de Gábor).

Aquí hay una biblioteca que he creado que está basada en el código AOSP, que agrega tintado tanto a las preferencias como a los diálogos, agrega una barra de acciones y admite todas las versiones de la API 7:

https://github.com/AndroidDeveloperLB/MaterialPreferenceLibrary

Bueno, esto sigue siendo un problema para mí hoy (18 de noviembre de 2015). He intentado todas las soluciones de este hilo, pero había dos cosas principales que no pude resolver:

  • Aparecen pantallas de preferencia anidadas sin barra de herramientas
  • Las preferencias no tienen el aspecto Material en los dispositivos previos a Lollipop

Así que terminé creando una biblioteca con una solución más complicada. Básicamente, tuve que aplicar estilos internamente a las preferencias si estamos usando un dispositivo pre-Lollipop y también manejé las pantallas anidadas usando un fragmento personalizado (restaurando toda la jerarquía anidada aprovechando la tecla PreferenceScreen).

La biblioteca es esta: https://github.com/ferrannp/material-preferences

Y si está interesado en el código fuente (demasiado largo para publicarlo aquí), este es básicamente el núcleo del mismo: https://github.com/ferrannp/material-preferences/blob/master/library/src/main/ java / com / fnp / materialpreferences / PreferenceFragment.java