¿Cómo agregar la barra de acciones de la biblioteca de soporte a PreferenceActivity?
La compatibilidad de la barra de acciones se ha añadido a la biblioteca de soporte, revisión 18. Ahora tiene ActionBarActivity
clase para crear actividades con Barra de acción en versiones anteriores de Android.
¿Hay alguna forma de agregar la Barra de acciones de la biblioteca de soporte a PreferenceActivity
?
Anteriormente usé ActionBarSherlock y tiene SherlockPreferenceActivity
.
8 answers
EDITAR: En appcompat-v7 22.1.0 Google agregó la clase abstracta AppCompatDelegate como un delegado que puede usar para extender el soporte de AppCompat a cualquier actividad.
Úsalo así:
...
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 .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-22 17:26:28
Actualmente no hay manera de lograr con AppCompat. He abierto un micrófono interno.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-26 08:53:44
He logrado crear una solución similar a la que usa Google Play Store. Enlace a la respuesta original
Por favor, encuentre el Repositorio de GitHub: Aquí
Muy similar a su propio código, pero se agregó xml para permitir el título del conjunto:
Seguir utilizando 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 :
ACTUALIZACIÓN (Compatibilidad con Pan de Jengibre) :
Como se señaló aquí , los dispositivos de pan de jengibre están devolviendo NullPointerException en esta línea:
LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
ARREGLO:
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: SOLUCIÓN DE TINTADO
Como se ha señalado en muchas notas de desarrollo PreferenceActivity
no admite el teñido de elementos, sin embargo, utilizando algunas clases internas puede lograr esto. Eso es hasta que se eliminen estas clases. (Trabaja usando AppCompat support-v7 v21. 0.3).
Añádanse 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 anula 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:
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 (aún invalidando 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;
}
PREFERENCIA ANIDADA PANTALLAS
Muchas personas están experimentando problemas con la inclusión de la barra de herramientas en anidados <PreferenceScreen />
s sin embargo, he encontrado una solución!! - ¡Después de mucho ensayo y error!
Añade lo siguiente a tu 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 los PreferenceScreen
son tan dolorosos es porque están basados como un diálogo de envoltura, por lo que necesitamos capturar el diseño del diálogo para agregarle la barra de herramientas.
Sombra de barra de herramientas
Por diseño importar el Toolbar
no permite para la elevación y el sombreado en dispositivos anteriores a la v21, por lo que si desea tener elevación en su Toolbar
debe 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 añadir la biblioteca add the Design Support como 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 la siguiente:
Si me estoy perdiendo algo por favor hágamelo saber a través de este repo y voy a investigar.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:28
Se encontró una implementación de PreferenceFragment basada en el fragmento support-v4:
Https://github.com/kolavar/android-support-v4-preferencefragment
Editar: Acabo de probarlo y funciona muy bien!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-21 08:34:53
Integrar PreferenceActivity
con ABC no es posible, al menos para mí. Probé las dos posibilidades que pude encontrar, pero ninguna funcionó:
Opción 1:
ActionBarPreferenceActivity
extiende PreferenceActivity
. Cuando usted hace esto usted consigue restringido por ActionBarActivityDelegate.createDelegate(ActionBarActivity activity)
. También es necesario implementar ActionBar.Callbacks
que no es accesible
Opción 2:
ActionBarPreferenceActivity
extiende ActionBarActivity
. Este enfoque requiere reescribir un nuevo PreferenceActivity
, PreferenceManager
y puede ser PreferenceFragment
lo que significa que necesita acceso a clases ocultas como com.android.internal.util.XmlUtils
La solución a esto solo puede venir de los desarrolladores de Google que implementan 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í.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-01 10:02:55
Fondo del problema:
El OP quiere saber cómo podemos poner MenuItem
s en el 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 propuso, para lograr el objetivo (y lo encontré en la Android Docs):
android:parentActivityName
El nombre de la clase del padre lógico de la actividad. El nombre aquí debe coincidir con el nombre de la clase dado a la atributo android: name del elemento correspondiente.
El sistema lee este atributo para determinar qué actividad debe ser iniciado cuando el uso presiona el botón Arriba en la barra de acciones. El sistema también puede utilizar esta información para sintetizar una pila posterior de actividades con TaskStackBuilder.
Para admitir los niveles de API 4 a 16, también puede declarar la actividad principal con un elemento que especifica un valor para "androide.apoyo.PARENT_ACTIVITY". Para 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 haz lo que normalmente harías en tu onOptionsItemSelected()
. Dado que es parte de Android Docs, no tiene efectos secundarios.
Feliz codificación. :)
Actualización:
Esta solución ya no funciona si estás apuntando a Lollipop. Si estás usando AppCompat, esta respuesta es lo que deberías estar buscando.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:17:55
Pude obtener android.app.Actionbar
usando getActionBar()
. Devolvió un valor null 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. Asumo que esto solo funcionará para ciertos niveles de construcción. Así que es posible que desee hacer una comprobación para el número de compilación o comprobar si el valor devuelto es null.
Estará bien para mí porque la aplicación en la que estoy trabajando es para ICS/4.0
+.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-22 20:14:57
Ahora se ha publicado la respuesta oficial para este problema. Es la biblioteca Soporte de Preferencias v7/v14.
Consulte ¿Cómo usar la biblioteca de Soporte de preferencias v7/v14? para la discusión cómo usarlo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:17