wake-up-neo.com

Wie füge ich die Aktionsleiste aus der Support-Bibliothek in PreferenceActivity hinzu?

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.

128
Roman

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 .

128

Mit AppCompat ist dies derzeit nicht möglich. Ich habe intern einen Bug geöffnet.

78
Chris Banes

Es ist mir gelungen, eine Problemumgehung zu erstellen, die der im Google Play Store verwendeten ähnelt. Link zur ursprünglichen Antwort

Finden Sie bitte das GitHub Repo: hier


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 :

example


UPDATE (Lebkuchen-Kompatibilität):

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();

FIX:

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:

example 2


AppCompat 22.1

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.


Symbolleiste Schatten

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'

Android 6.0

Ich habe das gemeldete überlappende Problem untersucht und kann es nicht reproduzieren.

Der wie oben verwendete vollständige Code erzeugt Folgendes:

enter image description here

Wenn ich etwas vermisse, lass es mich bitte über dieses Repo wissen und ich werde es untersuchen.

24
David Passmore

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!

12
Ostkontentitan

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:

Option 1:

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

Option 2:

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 .

3
Maxwell Weru

Problem Hintergrund:

Das OP möchte wissen, wie wir MenuItems 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.

Meine Lösung:

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. :)

Aktualisieren:

Diese Lösung funktioniert nicht mehr, wenn Sie auf Lollipop abzielen. Wenn Sie AppCompat verwenden, ist this die Antwort, nach der Sie suchen sollten.

3
Sufian

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.

1
RCB

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.