La compatibilité de la barre d’action a été ajoutée à la bibliothèque de support, révision 18. Elle dispose maintenant de la classe ActionBarActivity
pour la création d’activités avec Action Bar sur les anciennes versions d’Android.
Est-il possible d'ajouter Action Bar depuis la bibliothèque de support dans PreferenceActivity
?
Auparavant, je utilisais ActionBarSherlock et il a SherlockPreferenceActivity
.
EDIT: Dans appcompat-v7 22.1.0, Google a ajouté la classe abstraite AppCompatDelegate en tant que délégué que vous pouvez utiliser pour étendre la prise en charge d'AppCompat à toute activité.
Utilisez-le comme ceci:
...
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;
}
}
Plus de piratage. Code extrait de AppCompatPreferenceActivity.Java .
Il n'y a actuellement aucun moyen de réaliser avec AppCompat. J'ai ouvert un bug en interne.
J'ai réussi à créer une solution de contournement similaire à celle utilisée par le Google Play Store. Lien vers la réponse originale
Très similaire à votre propre code mais ajouté XML pour permettre le titre du jeu:
Continuer à utiliser 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 :
Comme indiqué ici , les périphériques Gingerbread retournent une exception NullPointerException sur cette ligne:
LinearLayout root = (LinearLayout)findViewById(Android.R.id.list).getParent().getParent().getParent();
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();
}
});
}
}
Tout problème avec ce qui précède faites le moi savoir!
MISE À JOUR 2: CONTOURNEMENT DE LA TEINTE
Comme indiqué dans de nombreuses notes de dev, PreferenceActivity
ne prend pas en charge la teinte des éléments. Toutefois, en utilisant quelques classes internes, vous POUVEZ y parvenir. C'est jusqu'à ce que ces classes sont supprimées. (Fonctionne avec appCompat support-v7 v21.0.3).
Ajoutez les importations suivantes:
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;
Puis substituez la méthode 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 a introduit de nouveaux éléments teintés, ce qui signifie qu'il n'est plus nécessaire d'utiliser les classes internes pour obtenir le même effet que la dernière mise à jour. Suivez plutôt ceci (en remplaçant toujours 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;
}
ECRANS DE PREFERENCE NESTED
Beaucoup de gens rencontrent des problèmes pour inclure la barre d'outils dans les <PreferenceScreen />
Imbriqués, cependant, j'ai trouvé une solution! - Après beaucoup d'essais et d'erreurs!
Ajoutez ce qui suit à votre 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 raison pour laquelle PreferenceScreen
est un problème, c'est parce qu'ils sont basés sur une boîte de dialogue wrapper. Nous devons donc capturer la présentation de la boîte de dialogue pour y ajouter la barre d'outils.
De par sa conception, l'importation de Toolbar
ne permet pas l'élévation ni l'ombrage dans les périphériques antérieurs à la v21, donc si vous souhaitez avoir une élévation sur votre Toolbar
, vous devez l'envelopper dans 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>
Sans oublier d’ajouter l’ajout de la bibliothèque Design Support en tant que dépendance dans le fichier 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'
J'ai enquêté sur le problème de chevauchement signalé et je ne peux pas le reproduire.
Le code complet utilisé ci-dessus produit les éléments suivants:
Si je manque quelque chose s'il vous plaît faites le moi savoir via ce repo et je vais enquêter.
Trouvé une implémentation de PreferenceFragment basée sur le fragment support-v4:
https://github.com/kolavar/Android-support-v4-preferencefragment
Edit: Je viens de le tester et ça marche très bien!
Intégrer PreferenceActivity
avec ABC n'est pas possible, du moins pour moi. J'ai essayé les deux possibilités que j'ai pu trouver mais aucune n'a fonctionné:
ActionBarPreferenceActivity
étend PreferenceActivity
. Lorsque vous faites cela, vous êtes limité par ActionBarActivityDelegate.createDelegate(ActionBarActivity activity)
. Aussi, vous devez implémenter ActionBar.Callbacks
qui n'est pas accessible
ActionBarPreferenceActivity
étend ActionBarActivity
. Cette approche nécessite la réécriture d’un tout nouveau PreferenceActivity
, PreferenceManager
et peut être PreferenceFragment
, ce qui signifie que vous devez avoir accès à des classes cachées comme com.Android.internal.util.XmlUtils
La solution à ce problème ne peut venir que des développeurs Google mettant en œuvre un ActionBarWrapper
pouvant être ajouté à toute activité.
Si vous avez vraiment besoin d'une activité de préférence, mon conseil pour l'instant est ActionBarSherlock
.
Cependant, j'ai réussi à l'implémenter ici .
L'OP veut savoir comment on peut mettre MenuItem
s dans ActionBar
de PreferenceActivity
pour pré-Honeycomb car la bibliothèque de support d'Android a un bogue qui ne permet pas que cela se produise.
J'ai trouvé un moyen beaucoup plus propre que celui déjà proposé pour atteindre l'objectif (et je l'ai trouvé dans le Android Docs ):
Android:parentActivityName
Nom de classe du parent logique de l'activité. Le nom ici doit correspondre au nom de classe attribué à l'attribut Android: name de l'élément correspondant.
Le système lit cet attribut pour déterminer quelle activité doit être lancée lorsque l'utilisateur appuie sur le bouton Haut de la barre d'actions. Le système peut également utiliser ces informations pour synthétiser une pile d'activités en arrière avec TaskStackBuilder.
Pour prendre en charge les niveaux 4 à 16 de l'API, vous pouvez également déclarer l'activité mère avec un élément spécifiant une valeur pour "Android.support.PARENT_ACTIVITY". Par exemple:
<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>
Maintenant, faites ce que vous feriez normalement dans votre onOptionsItemSelected()
. Puisqu'il fait partie de Android Docs, il n'a pas d'effets secondaires.
Bonne codage. :)
Cette solution ne fonctionne plus si vous ciblez Lollipop. Si vous utilisez AppCompat, this answer est ce que vous devriez rechercher.
J'ai pu obtenir Android.app.Actionbar
En utilisant getActionBar()
. Il a renvoyé une valeur nulle au début ... puis je suis allé au manifeste et j'ai changé le thème en:
Android:theme="@style/Theme.AppCompat"
Ensuite, j'ai pu avoir la barre d'action à nouveau. Je suppose que cela ne fonctionnera que pour certains niveaux de construction. Donc, vous voudrez peut-être vérifier le numéro de build ou vérifier si la valeur renvoyée est null.
Tout ira bien pour moi car l'application sur laquelle je travaille est pour ICS/4.0
+.
Maintenant, la réponse officielle à ce problème a été publiée. Il s’agit de la bibliothèque v7/v14 Preference Support .
Voir Comment utiliser la bibliothèque de support de préférence v7/v14? pour la discussion sur l'utilisation.