¿Cómo agregar la barra de acción de la biblioteca de soporte en PreferenceActivity?

La compatibilidad con la barra de acciones se ha añadido a la biblioteca de soporte, revisión 18. Ahora tiene la clase ActionBarActivity para crear actividades con la barra de acciones en versiones anteriores de Android.

¿Hay alguna manera de agregar barra de acción de la biblioteca de soporte en PreferenceActivity ?

Anteriormente usé ActionBarSherlock y tiene SherlockPreferenceActivity .

EDIT: En appcompat-v7 22.1.0 Google agregó la clase abstracta AppCompatDelegate como un delegado que puede utilizar para extender el soporte de AppCompat a cualquier actividad.

Utilícelo de esta manera:

 ... import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatDelegate; import android.support.v7.widget.Toolbar; ... public class SettingsActivity extends PreferenceActivity { private AppCompatDelegate mDelegate; @Override protected void onCreate(Bundle savedInstanceState) { getDelegate().installViewFactory(); getDelegate().onCreate(savedInstanceState); super.onCreate(savedInstanceState); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); getDelegate().onPostCreate(savedInstanceState); } public ActionBar getSupportActionBar() { return getDelegate().getSupportActionBar(); } public void setSupportActionBar(@Nullable Toolbar toolbar) { getDelegate().setSupportActionBar(toolbar); } @Override public MenuInflater getMenuInflater() { return getDelegate().getMenuInflater(); } @Override public void setContentView(@LayoutRes int layoutResID) { getDelegate().setContentView(layoutResID); } @Override public void setContentView(View view) { getDelegate().setContentView(view); } @Override public void setContentView(View view, ViewGroup.LayoutParams params) { getDelegate().setContentView(view, params); } @Override public void addContentView(View view, ViewGroup.LayoutParams params) { getDelegate().addContentView(view, params); } @Override protected void onPostResume() { super.onPostResume(); getDelegate().onPostResume(); } @Override protected void onTitleChanged(CharSequence title, int color) { super.onTitleChanged(title, color); getDelegate().setTitle(title); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); getDelegate().onConfigurationChanged(newConfig); } @Override protected void onStop() { super.onStop(); getDelegate().onStop(); } @Override protected void onDestroy() { super.onDestroy(); getDelegate().onDestroy(); } public void invalidateOptionsMenu() { getDelegate().invalidateOptionsMenu(); } private AppCompatDelegate getDelegate() { if (mDelegate == null) { mDelegate = AppCompatDelegate.create(this, null); } return mDelegate; } } 

No más hacking. Código tomado de AppCompatPreferenceActivity.java .

Actualmente no hay forma de lograrlo con AppCompat. He abierto un error internamente.

He logrado crear una solución parecida a la que usa Google Play Store. Enlace a la respuesta original

Por favor encuentre el Repo de GitHub: Aquí


Muy similar a su propio código, pero añadió xml para permitir el título de conjunto:

Continuar usando PreferenceActivity :

settings_toolbar.xml :

 <?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/toolbar" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="?attr/actionBarSize" app:navigationContentDescription="@string/abc_action_bar_up_description" android:background="?attr/colorPrimary" app:navigationIcon="?attr/homeAsUpIndicator" app:title="@string/action_settings" /> 

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


UPDATE (Compatibilidad de pan de jengibre):

Como se señala aquí , Gingerbread Devices están devolviendo 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 ha señalado en muchas notas de desarrollo, PreferenceActivity no soporta el tintado de elementos, sin embargo, utilizando algunas clases internas PUEDES lograr esto. Eso es hasta que estas clases se eliminan. (Works utilizando 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; 

A continuación, 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 teñidos, 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 seguir esto (todavía sobreescribiendo 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 NESTED

Muchas personas están experimentando problemas con la inclusión de la barra de herramientas en <PreferenceScreen /> s anidada sin embargo, he encontrado una solución !! – Después de un montón de ensayo y error!

Añada 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(); } }); } 

La razón por la que PreferenceScreen son tan dolorosos es porque se basan en un diálogo de contenedor, por lo que necesitamos capturar el diseño del diálogo para añadir la barra de herramientas.


Sombra de la barra de herramientas

Por diseño la importación de la Toolbar no permite la elevación y la sombra en los dispositivos pre-v21, por lo que si desea tener la elevación en su Toolbar que necesita para envolverlo en un AppBarLayout :

`Settings_toolbar.xml:

 <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar .../> </android.support.design.widget.AppBarLayout> 

Sin olvidar agregar la biblioteca de soporte de diseño 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

He investigado el problema de superposición reportado y no puedo reproducir el problema.

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

Introduzca aquí la descripción de la imagen

Si me falta algo, por favor, hágamelo saber a través de este repo y voy a investigar.

Se encontró una implementación de PreferenceFragment basada en soporte-v4 Fragmento:

https://github.com/kolavar/android-support-v4-preferencefragment

Edit: Acabo de probarlo y su funcionamiento grande!

Integración de PreferenceActivity con ABC no es posible, al menos para mí. He probado las dos posibilidades que pude encontrar, pero ninguno funcionó:

Opción 1:

ActionBarPreferenceActivity amplía PreferenceActivity . Al hacerlo, obtiene restringido por ActionBarActivityDelegate.createDelegate(ActionBarActivity activity) . También es necesario implementar ActionBar.Callbacks que no es accesible

Opcion 2:

ActionBarPreferenceActivity amplía ActionBarActivity . Este enfoque requiere la reescritura de una nueva PreferenceActivity , PreferenceManager y puede ser PreferenceFragment que significa que usted necesita el acceso a las clases ocultas como com.android.internal.util.XmlUtils La solución a esto sólo puede venir de Google devs la implementación de un ActionBarWrapper que se puede agregar a Cualquier actividad.

Si realmente necesita una actividad de preferencia, mi consejo por ahora es ActionBarSherlock .

Sin embargo, logré implementarlo aquí .

Antecedentes del problema:

El OP quiere saber cómo podemos poner MenuItem s en la ActionBar de PreferenceActivity para pre-Honeycomb porque la biblioteca de soporte de Android tiene un error que no permite que esto suceda.

Mi solución:

He encontrado una manera mucho más limpia, de lo que ya se ha propuesto, para alcanzar el objetivo (y lo encontré en los documentos de Android ):

android:parentActivityName

El nombre de clase del padre lógico de la actividad. El nombre aquí debe coincidir con el nombre de clase dado al atributo android: name del elemento correspondiente.

El sistema lee este atributo para determinar qué actividad debe iniciarse cuando el uso presiona el botón Arriba en la barra de acción. El sistema también puede usar esta información para sintetizar una pila trasera de actividades con TaskStackBuilder.

Para admitir los niveles API 4 a 16, también puede declarar la actividad principal con un elemento que especifica un valor para "android.support.PARENT_ACTIVITY". Por ejemplo:

 <activity android:name="com.example.app.ChildActivity" android:label="@string/title_child_activity" android:parentActivityName="com.example.myfirstapp.MainActivity" > <!-- Parent activity meta-data to support API level 4+ --> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.example.app.MainActivity" /> </activity> 

Ahora haga lo que normalmente haría en su onOptionsItemSelected() . Dado que es parte de Android Docs, no tiene efectos secundarios.

Codificación feliz. 🙂

Actualizar:

Esta solución ya no funciona si apunta a Lollipop. Si estás usando AppCompat, esta respuesta es lo que deberías buscar.

Podía conseguir android.app.Actionbar usando getActionBar() . Regresó un valor nulo al principio … luego fui al manifiesto y cambié el tema a:

 android:theme="@style/Theme.AppCompat" 

Entonces pude tener la barra de acción de nuevo. Estoy asumiendo que esto trabajará solamente para ciertos niveles de la estructura. Por lo tanto, es posible que desee realizar una comprobación del número de compilación o comprobar si el valor devuelto es nulo.

Estará bien para mí porque la aplicación en la que estoy trabajando es para ICS/4.0 +.

Ahora la respuesta oficial para este problema se ha lanzado. Es la biblioteca de soporte de preferencias v7 / v14 .

Consulte ¿Cómo utilizar la biblioteca de compatibilidad de preferencias v7 / v14? Para la discusión cómo usarlo.

  • Nuevo tema incorrecto de la biblioteca de soporte de preferencias en tiempo de ejecución
  • Preferencia en el oyente de cambio
  • DialogFragment en PreferenceActivity
  • PreferenceActivity funciona correctamente en Android 2.1, pero no en 4.1 (acolchado)
  • Fragmento abierto del fragmento Preferencia; Cambiar el diseño de la barra de acción desde la pantalla de Preferencias anidadas en Android
  • Configuración del diseño de preferencias y cambio del atributo en él
  • Cree su propia preferencia de SwitchCompat
  • Recargar preferencias en PreferenciaActividad al reanudar
  • SharedPreferences no se guardará / cargará en PreferenciaActividad
  • Valor predeterminado del tono de llamada de preferencia
  • Cómo utilizar la nueva API de las preferencias, presentada en la nueva biblioteca de soporte 23
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.