Die Action Bar-Kompatibilität wurde der Support-Bibliothek, Revision 18, hinzugefügt. Sie enthält jetzt die Klasse ActionBarActivity
zum Erstellen von Aktivitäten mit der Action Bar unter älteren Android-Versionen.
Gibt es eine Möglichkeit, die Aktionsleiste aus der Unterstützungsbibliothek in PreferenceActivity
einzufügen?
Früher habe ich ActionBarSherlock verwendet und es hat SherlockPreferenceActivity
.
BEARBEITEN: In appcompat-v7 22.1.0 hat Google die abstrakte Klasse AppCompatDelegate als Delegat hinzugefügt, mit der Sie die Unterstützung von AppCompat auf alle Aktivitäten ausweiten können.
Benutze es so:
...
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;
}
}
Nie mehr hacken. Code aus AppCompatPreferenceActivity.Java .
Mit AppCompat ist dies derzeit nicht möglich. Ich habe intern einen Bug geöffnet.
Es ist mir gelungen, eine Problemumgehung zu erstellen, die der im Google Play Store verwendeten ähnelt. Link zur ursprünglichen Antwort
Sehr ähnlich zu Ihrem eigenen Code, aber hinzugefügtes XML, um den eingestellten Titel zu ermöglichen:
Verwenden Sie weiterhin 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 :
Wie bereits erwähnt hier , geben Gingerbread Devices in dieser Zeile NullPointerException zurück:
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();
}
});
}
}
Probleme mit den oben genannten lassen Sie es mich wissen!
UPDATE 2: ABHILFE ZUM TÖNEN
Wie in vielen Dev Notes erwähnt, unterstützt PreferenceActivity
das Abtönen von Elementen nicht. Durch die Verwendung einiger interner Klassen können Sie dies jedoch erreichen. Das ist, bis diese Klassen entfernt werden. (Funktioniert mit appCompat support-v7 v21.0.3).
Fügen Sie die folgenden Importe hinzu:
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;
Überschreiben Sie dann die Methode 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:
In AppCompat 22.1 wurden neue getönte Elemente eingeführt, sodass die internen Klassen nicht mehr verwendet werden müssen, um den gleichen Effekt wie beim letzten Update zu erzielen. Folgen Sie stattdessen diesen Anweisungen (überschreiben Sie immer noch 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;
}
NESTED PRÄFERENZBILDSCHIRME
Viele Leute haben Probleme damit, die Symbolleiste in verschachtelte <PreferenceScreen />
s aber ich habe eine lösung gefunden !! - Nach vielem Ausprobieren!
Fügen Sie Ihrem SettingsActivity
Folgendes hinzu:
@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();
}
});
}
Der Grund, warum PreferenceScreen
so schmerzhaft ist, liegt darin, dass sie auf einem Wrapper-Dialogfeld basieren. Daher müssen wir das Dialogfeldlayout erfassen, um die Symbolleiste hinzuzufügen.
Durch das Importieren von Toolbar
ist in Geräten vor Version 21 keine Erhöhung und Schattenbildung möglich. Wenn Sie also eine Erhöhung in Ihrem Toolbar
haben möchten, müssen Sie diese in ein AppBarLayout
einwickeln ] _:
`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>
Nicht zu vergessen, das Hinzufügen der Design Support-Bibliothek als Abhängigkeit in build.gradle
Datei:
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'
Ich habe das gemeldete überlappende Problem untersucht und kann es nicht reproduzieren.
Der wie oben verwendete vollständige Code erzeugt Folgendes:
Wenn ich etwas vermisse, lass es mich bitte über dieses Repo wissen und ich werde es untersuchen.
Es wurde eine PreferenceFragment-Implementierung basierend auf dem support-v4-Fragment gefunden:
https://github.com/kolavar/Android-support-v4-preferencefragment
Edit: Ich habe es gerade getestet und es funktioniert super!
Die Integration von PreferenceActivity
in ABC ist zumindest für mich nicht möglich. Ich habe die beiden Möglichkeiten ausprobiert, aber keine hat funktioniert:
ActionBarPreferenceActivity
erweitert PreferenceActivity
. Wenn Sie dies tun, werden Sie durch ActionBarActivityDelegate.createDelegate(ActionBarActivity activity)
eingeschränkt. Außerdem müssen Sie ActionBar.Callbacks
Implementieren, auf das nicht zugegriffen werden kann
ActionBarPreferenceActivity
erweitert ActionBarActivity
. Dieser Ansatz erfordert das Umschreiben eines völlig neuen PreferenceActivity
, PreferenceManager
und kann PreferenceFragment
sein, was bedeutet, dass Sie Zugriff auf versteckte Klassen wie com.Android.internal.util.XmlUtils
Benötigen kommen von Google-Entwicklern, die ein ActionBarWrapper
implementieren, das zu jeder Aktivität hinzugefügt werden kann.
Wenn Sie wirklich eine Präferenzaktivität benötigen, lautet mein Rat vorerst ActionBarSherlock
.
Ich habe es jedoch geschafft hier .
Das OP möchte wissen, wie wir MenuItem
s in ActionBar
von PreferenceActivity
für Pre-Honeycomb einfügen können, da die Support-Bibliothek von Android einen Fehler aufweist, der dies nicht zulässt.
Ich habe einen viel saubereren Weg gefunden, als bereits vorgeschlagen, um das Ziel zu erreichen (und fand ihn in Android Docs ):
Android:parentActivityName
Der Klassenname des logischen übergeordneten Elements der Aktivität. Der Name hier muss mit dem Klassennamen übereinstimmen, der dem Android: name-Attribut des entsprechenden Elements zugewiesen wurde.
Das System liest dieses Attribut, um zu bestimmen, welche Aktivität gestartet werden soll, wenn die Verwendung die Schaltfläche Nach oben in der Aktionsleiste drückt. Das System kann diese Informationen auch verwenden, um einen Stapel von Aktivitäten mit TaskStackBuilder zu synthetisieren.
Zur Unterstützung der API-Stufen 4 bis 16 können Sie die übergeordnete Aktivität auch mit einem Element deklarieren, das einen Wert für "Android.support.PARENT_ACTIVITY" angibt. Beispielsweise:
<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>
Tun Sie nun, was Sie normalerweise in Ihrer onOptionsItemSelected()
tun würden. Da es ein Teil von Android Docs ist, hat es keine Nebenwirkungen.
Fröhliches Codieren. :)
Diese Lösung funktioniert nicht mehr, wenn Sie auf Lollipop abzielen. Wenn Sie AppCompat verwenden, ist this die Antwort, nach der Sie suchen sollten.
Ich konnte Android.app.Actionbar
Mit getActionBar()
erhalten. Zuerst wurde ein Nullwert zurückgegeben. Dann ging ich zum Manifest und änderte das Thema in:
Android:theme="@style/Theme.AppCompat"
Dann konnte ich die Actionbar wieder haben. Ich gehe davon aus, dass dies nur für bestimmte Build-Ebenen funktioniert. Vielleicht möchten Sie die Build-Nummer überprüfen oder prüfen, ob der zurückgegebene Wert null ist.
Für mich ist das in Ordnung, da die App, an der ich arbeite, für ICS/4.0
+ Ist.
Jetzt wurde die offizielle Antwort für dieses Problem veröffentlicht. Dies ist die v7/v14 Preference Support Bibliothek.
Siehe Wie verwende ich die Preference Support-Bibliothek von v7/v14? für eine Erläuterung der Verwendung.