Symbolleiste und kontextbezogene Aktionsleiste mit AppCompat-v7

182

Ich arbeite an der Verwendung der neu hinzugefügten Symbolleiste, die in Lollipop und der AppCompat-v7-Bibliothek eingeführt wurde. Ich folgte dieser Anleitung beim Einrichten der Symbolleiste befolgt. Beim Aufrufen von etwas, das die kontextbezogene Aktionsleiste aufruft (z. B. Hervorheben von Text zum Kopieren / Einfügen), wird die Symbolleiste auf der Seite nach unten gedrückt. Sie können im Bild unten auf der Seite sehen, wovon ich spreche:

Also habe ich es im Wesentlichen so eingerichtet. Ich habe die Symbolleiste in einer XML-Datei definiert, die ich mit Include-Tags verwende:

<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimary"/>

Dann instanziiere ich es aus meiner Sicht:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/root"
    tools:context=".MainActivity">

    <include
        layout="@layout/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/> 

    <!-- Rest of view -->

    </LinearLayout>

Im Code habe ich es so eingerichtet:

    // On Create method of activity:
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

Weiß jemand, wie man es so macht, dass die Contextual ActionBar über die Symbolleiste kommt?

Symbolleiste und kontextbezogene Aktionsleiste

Ariets
quelle
Welches Thema verwendet Ihre Aktivität?
Alanv
David, ich habe gerade auf den Link geklickt und es scheint für mich zu funktionieren.
Ariets

Antworten:

319

Aktualisieren:

Lösung: Verwenden Sie die Eigenschaft windowActionModeOverlay . Stellen Sie dies in Ihrem Thema ein:

<item name="windowActionModeOverlay">true</item>

und der Aktionsmodus wird über der Aktionsleiste angezeigt, anstatt ihn nach unten zu drücken. (Wenn Sie nicht das neueste AppCompat verwenden, müssen Sie der Eigenschaft das Präfix "android:" hinzufügen.) Grundsätzlich wird AppCompat darüber informiert, dass sich oben auf dem Bildschirm eine Symbolleiste befindet und dass der ActionMode darüber gezeichnet werden soll.


Alte Antwort / Problemumgehung:

Ich bin auf das gleiche Problem gestoßen. Unabhängig davon, welches Thema ich festgelegt habe, wird die als Aktionsleiste festgelegte Symbolleiste immer nach unten gedrückt. Ich habe es mit und ohne Support-Bibliothek versucht, aber es war egal.

Leider konnte ich das Problem nicht beheben, daher habe ich stattdessen eine Problemumgehung erstellt. In meinem ActionModeCallback‚s onCreateActionModeich die Aktionsleiste verstecken:

actionBarToolbar.setVisibility(View.GONE);

und in onDestroyActionModezeige ich es nochmal:

actionBarToolbar.setVisibility(View.VISIBLE);

Das Ausblenden / Anzeigen geschieht so schnell, dass es auf meinen Testgeräten nicht auffällt. Es gibt natürlich einen Nachteil: Obwohl die Enter-Animation immer noch funktioniert, geht die Exit-Animation der kontextbezogenen Aktionsleiste verloren, da die Symbolleiste sofort darüber erscheint. Aber bis wir auf eine bessere Lösung stoßen, bleiben wir wohl dabei.


(Meine Aktivität erweitert tatsächlich eine benutzerdefinierte BaseActivityKlasse, deren Methode getActionBarToolbar()aus dem Quellcode der Google I / O 2014-App stammt , sodass ich die Symbolleiste problemlos abrufen kann:

BaseActivity activity = (BaseActivity) getActivity();
activity.getActionBarToolbar().setVisibility(View.GONE);

Schade, dass die E / A-App die kontextbezogene Aktionsleiste nicht verwendet.)

Jacob Ras
quelle
Ja, dies war die einzige Lösung, zu der ich auch kommen konnte. Es gibt jedoch Fälle, in denen die kontextbezogene Aktionsleiste vom System aus ausgeführt wird (z. B. in einer WebView oder mit einem EditText). Für die Sie keine Rückrufe erhalten. Also, wie würden Sie es dafür zeigen / verstecken? (Oder irre ich mich und Sie können tatsächlich die Rückrufe für das CAB mit diesen erhalten)?
Ariets
1
Ja, Sie können dafür TextView.setCustomSelectionActionModeCallback () verwenden , wie Aleksandar in seiner Antwort beschrieben hat.
Jacob Ras
1
Oh, ich kann meinen Kommentar schon nicht mehr aktualisieren. Kleiner Zusatz: Es scheint, dass setCustomSelectionActionModeCallback nicht mit dem ActionModeCallback aus der Support-Bibliothek verwendet werden kann. Ich verwende eine VERSION.SDK_INT-Prüfung, um sie festzulegen. Es muss noch getestet werden, ob das Problem auch bei Geräten vor Honeycomb auftritt.
Jacob Ras
@ariets siehe meine aktualisierte Antwort. Ich fühle mich ein bisschen enttäuscht, weil ich diese Eigenschaft komplett vergessen habe, aber zumindest können wir die Problemumgehung jetzt loswerden ;-)
Jacob Ras
1
Komisch, dass ich die neueste Version verwende (kompiliere 'com.android.support:appcompat-v7:22.0.0'), aber ich muss den android: part
weglassen, damit
16

Starten Sie es nicht in Ihrer Aktivität, sondern in Ihrer Symbolleiste. In Ihrer Aktivität:

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.startActionMode(mActionModeCallback)

und du musst verwenden

<item name="windowActionModeOverlay">true</item>
Frank
quelle
für mich tut es für android.support.v7.app.ActionBar
Frank
Ich erhalte diesen Fehler-> startActionMode (android.view.ActionMode.Callback) in View kann nicht auf (android.support.v7.view.ActionMode.Callback) angewendet werden
Faheem
Ah, okay. Meine Min-Version ist nicht kleiner als 11. Ich kann also einen android.view.ActionMode verwenden. Rückruf auf einer android.support.v7.widget.Toolbar, ich habe android.support.v7.view.ActionMode.Callback nie verwendet.
Frank
Es ist erwähnenswert AppCompatActivity.startSupportActionMode(callback), Kompatibilität mit Attributen wie app:iconTintim Menüpunkt xmls zu erhalten.
Geekley
14

Nur eine kleine Ergänzung: Für

<item name="windowActionModeOverlay">true</item>
super.onCreate(savedInstanceState) Um zu arbeiten, ist es wichtig, VOR dem Anruf anzurufensetContentView(R.layout.your_activity) Ihrer Aktivität . In diesem Fall macht es wirklich einen Unterschied!

Daniel Veihelmann
quelle
11

In meinem Fall <item name="windowActionModeOverlay">true</item>hat nicht funktioniert, aber diese Arbeit : <item name="android:windowActionModeOverlay">true</item>, das androidist der Schlüssel.

Jenkyn
quelle
8
Sie verwenden <item name="windowActionModeOverlay">true</item>mit der Appcompat-Symbolleiste, andernfalls verwenden Sie den androidNamespace.
Javier Mendonça
Keine Verwendung für mich in meinem Layout füge Symbolleiste hinzu, in der Aktivität Initialisieren Symbolleiste und Setsupport wahr erledigt bitte helfen Sie mir
Harsha
<item name = "windowActionModeOverlay"> true </ item> hat wie erwartet funktioniert!
Francois
8

Jacobs Lösung funktionierte für mich, aber die kontextbezogene ActionBar war transparent und die Symbolleiste durch sie sichtbar. Dies kann wie folgt gelöst werden:

<style name="AppTheme.Base" parent="Theme.AppCompat.Light">
    ....
    ....
    <item name="actionModeStyle">@style/CustomActionMode</item>
</style>

<style name="CustomActionMode" parent="@style/Widget.AppCompat.ActionMode">
    <item name="background">@color/primary_material_light</item>
</style>

Das Thema "AppTheme.Base" muss auf die Symbolleiste angewendet werden.

Weitere Details zum kontextbezogenen ActionBar-Styling:

Anpassen der Kontextaktionsleiste mithilfe von appCompat im Materialdesign

Pete
quelle
0

Sehr nützliche Methode, um die Symbolleiste nach vorne zu bringen toolbar.bringToFront()

kunal.c
quelle
2
View.bringToFront()ist ein sehr schwerer Betrieb und sollte generell um jeden Preis vermieden werden.
Dominus
Sie haben Recht, aber für Animationen, z. B. von oben nach unten, überlappt die Symbolleiste. Daher müssen wir toolbar.bringToFront () verwenden, um unter der Symbolleiste zu animieren. Wenn es eine alternative Möglichkeit gibt, die Sie teilen können
:)
0

Ein weiterer kleiner Zusatz: Stellen Sie sicher, dass in der Aktivität mindestens ein leerer Bildschirm festgelegt ist, setContentView(R.layout.empty_screen)wenn Sie die gesamte Benutzeroberfläche in Fragmenten laden ( ft.replace(android.R.id.content, fragment)).

Andreas Wenger
quelle