android - poner - ¿Cómo agregar Action Bar desde la biblioteca de soporte a PreferenceActivity?
poner toolbar android studio (8)
La compatibilidad con Action Bar se ha agregado a la biblioteca de soporte, revisión 18. Ahora tiene la clase ActionBarActivity
para crear actividades con Action Bar en versiones anteriores de Android.
¿Hay alguna manera de agregar Action Bar desde la biblioteca de soporte en PreferenceActivity
?
Previamente utilicé ActionBarSherlock y tiene SherlockPreferenceActivity
.
Antecedentes del problema:
El OP quiere saber cómo podemos colocar MenuItem
en 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 clara, que ya se propuso, para lograr 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 la clase dada al atributo android: name del elemento correspondiente.
El sistema lee este atributo para determinar qué actividad se debe iniciar cuando el uso presiona el botón Arriba en la barra de acciones. El sistema también puede usar esta información para sintetizar una pila de actividades con TaskStackBuilder.
Para admitir los niveles API 4 - 16, también puede declarar la actividad principal con un elemento que especifique 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()
. Como es parte de Android Docs, no tiene efectos secundarios.
Feliz codificación. :)
Actualizar:
Esta solución ya no funciona si estás apuntando a Lollipop. Si está utilizando AppCompat, this respuesta es lo que debería estar buscando.
Actualmente no hay forma de lograrlo con AppCompat. He abierto un error internamente.
Ahora se ha lanzado la respuesta oficial para este problema. Es la biblioteca de soporte de preferencias v7 / v14 .
Consulte Cómo usar la biblioteca de soporte de preferencias v7 / v14? para la discusión cómo usarlo.
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.
Úselo 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 piratería. Código tomado de AppCompatPreferenceActivity.java .
He logrado crear una solución similar a la que usa Google Play Store. Enlace a la respuesta original
Encuentre el GitHub Repo: Here
Muy similar a su propio código, pero agregó xml para permitir el título del 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 :
ACTUALIZACIÓN (Gingerbread Compatibility):
Como se señala here , 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:
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 <PreferenceScreen />
anidado, 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:
<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 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:
Si me falta algo, házmelo saber a través de Here e investigaré.
La integración de PreferenceActivity
con ABC no es posible, al menos para mí. Intenté las dos posibilidades que pude encontrar, pero ninguna funcionó:
Opción 1:
ActionBarPreferenceActivity
extiende PreferenceActivity
. Cuando hace esto, obtiene restringido por ActionBarActivityDelegate.createDelegate(ActionBarActivity activity)
. También necesita implementar ActionBar.Callbacks
que no es accesible
Opcion 2:
ActionBarPreferenceActivity
extiende ActionBarActivity
. Este enfoque requiere volver a escribir una PreferenceActivity
completamente nueva, PreferenceManager
y puede ser un PreferenceFragment
que significa que necesita acceder a clases ocultas como com.android.internal.util.XmlUtils
La solución a esto solo puede provenir 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 here .
Pude obtener android.app.Actionbar
usando getActionBar()
. Al principio devolvió un valor nulo ... luego fui al manifiesto y cambié el tema a:
android:theme="@style/Theme.AppCompat"
Luego pude volver a tener la barra de acciones. Supongo que esto solo funcionará para ciertos niveles de compilación. Por lo tanto, es posible que desee verificar el número de compilación o verificar si el valor devuelto es nulo.
Estaré bien para mí porque la aplicación en la que estoy trabajando es para ICS/4.0
+.
Se encontró una implementación de PreferenceFragment basada en el fragmento de support-v4:
https://github.com/kolavar/android-support-v4-preferencefragment
Editar: ¡Acabo de probarlo y está funcionando genial!