Pasek narzędzi i kontekstowy pasek akcji z AppCompat-v7


182

Pracuję nad użyciem nowo dodanego paska narzędzi, który został wprowadzony w Lollipop i bibliotece AppCompat-v7. Postępowałem zgodnie z tym przewodnikiem na temat konfigurowania paska narzędzi. Zauważyłem, że kiedy wywołujesz coś, co wywołuje kontekstowy pasek narzędzi Actionbar (np. Zaznaczanie tekstu do kopiowania / wklejania), przesuwa pasek narzędzi w dół na stronie. Na dole strony możesz zobaczyć, o czym mówię:

Zasadniczo tak to skonfigurowałem. Mam pasek narzędzi zdefiniowany w pliku xml, którego używam z tagami dołączania:

<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"/>

Następnie w moim widoku tworzę instancję:

<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>

W kodzie skonfigurowałem to tak:

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

Czy ktoś wie, jak to zrobić, aby kontekstowy pasek akcji znalazł się nad paskiem narzędzi?

Pasek narzędzi i kontekstowy pasek akcji


Z jakiego motywu korzysta Twoja aktywność?
alanv

David, właśnie kliknąłem link i wydaje się, że działa dla mnie.
przybywa

Odpowiedzi:


320

Aktualizacja:

Rozwiązanie: użyj właściwości windowActionModeOverlay . Ustaw to w swoim motywie:

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

a tryb akcji zostanie wyświetlony nad paskiem akcji, zamiast przesuwać go w dół. (Jeśli nie używasz najnowszego AppCompat, musisz dodać do właściwości przedrostek „android:”). Zasadniczo informuje AppCompat, że masz pasek narzędzi umieszczony w górnej części ekranu i że powinien narysować na nim tryb ActionMode.


Stara odpowiedź / obejście:

Natrafiłem na ten sam problem. Bez względu na to, jaki motyw ustawię, zawsze przesuwa pasek narzędzi ustawiony jako ActionBar. Próbowałem z biblioteką wsparcia i bez niej, ale to nie miało znaczenia.

Niestety nie udało mi się tego naprawić, dlatego stworzyłem obejście. W moim ActionModeCallback„s onCreateActionModeukryć pasek działań:

actionBarToolbar.setVisibility(View.GONE);

i onDestroyActionModepokazuję to jeszcze raz:

actionBarToolbar.setVisibility(View.VISIBLE);

Ukrywanie / pokazywanie odbywa się tak szybko, że nie jest to zauważalne na moich urządzeniach testowych. Istnieje oczywiście pewna wada: chociaż animacja Enter nadal działa, animacja wyjścia z kontekstowego paska akcji ginie, ponieważ pasek narzędzi natychmiast się nad nim pojawia. Ale dopóki nie znajdziemy lepszego rozwiązania, myślę, że utknęliśmy z tym.


(Moja aktywność faktycznie rozszerza BaseActivityklasę niestandardową, która ma wywoływaną metodę getActionBarToolbar(), pobraną z kodu źródłowego aplikacji Google I / O 2014 , dzięki czemu mogę łatwo pobrać pasek narzędzi Toolbar:

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

Szkoda, że ​​aplikacja I / O nie używa kontekstowego paska akcji.)


Tak, to było jedyne rozwiązanie, do którego mogłem dojść. Są jednak przypadki, w których kontekstowy pasek akcji dzieje się z systemu (na przykład w WebView lub z EditText). Te, dla których nie otrzymujesz oddzwaniania. Więc jak poszedłbyś o pokazywanie / ukrywanie go w tym celu? (Czy też się mylę i można w rzeczywistości uzyskać oddzwanianie do CAB za ich pomocą)?
przybywa

1
Tak, możesz w tym celu TextView.setCustomSelectionActionModeCallback () , jak Aleksandar opisał w swojej odpowiedzi.
Jacob Ras,

1
Och, już nie mogę zaktualizować mojego komentarza. Mały dodatek: wygląda na to, że setCustomSelectionActionModeCallback nie może być używany z ActionModeCallback z biblioteki wsparcia. Korzystam z czeku VERSION.SDK_INT, aby go ustawić. Nadal trzeba sprawdzić, czy problem występuje również na urządzeniach sprzed plastra miodu.
Jacob Ras,

@ariets proszę zobaczyć moją zaktualizowaną odpowiedź. Mam wrażenie, że całkowicie zapomniałem o tej nieruchomości, ale przynajmniej teraz możemy pozbyć się obejścia ;-)
Jacob Ras,

1
Zabawne, że korzystam z najnowszego (kompilacja „com.android.support:appcompat-v7:22.0.0”), ale muszę pominąć Androida: część, żeby działało ...
Warpzit

16

Nie zaczynaj go od aktywności, ale na pasku narzędzi. W tobie aktywność:

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

i musisz użyć

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

dla mnie robi to dla android.support.v7.app.ActionBar
Frank

Otrzymuję ten błąd-> startActionMode (android.view.ActionMode.Callback) w widoku nie można zastosować do (android.support.v7.view.ActionMode.Callback)
Faheem

Ah, dobrze. Moja minimalna wersja nie jest mniejsza niż 11. Więc mogę użyć android.view.ActionMode. Oddzwonienie na pasku narzędzi android.support.v7.widget.Toolbar, nigdy nie korzystałem z android.support.v7.view.ActionMode.Callback.
Frank

Warto wspomnieć AppCompatActivity.startSupportActionMode(callback), aby uzyskać zgodność z atrybutami, takimi jak app:iconTintpozycja menu xmls.
geekley

14

Tylko mały dodatek: dla

<item name="windowActionModeOverlay">true</item>
do pracy ważne jest, aby zadzwonić super.onCreate(savedInstanceState) ZANIM zadzwonisz setContentView(R.layout.your_activity)w swojej działalności. To naprawdę robi różnicę w tym przypadku!


11

W moim przypadku <item name="windowActionModeOverlay">true</item>nie działa, ale ta praca: <item name="android:windowActionModeOverlay">true</item>The androidjest kluczem.


8
Korzystasz <item name="windowActionModeOverlay">true</item>z paska narzędzi appcompat, w przeciwnym razie korzystasz z androidprzestrzeni nazw.
Javier Mendonça,

bezużyteczne dla mnie w moim układzie dodaję pasek narzędzi, w czynności inicjalizuję pasek narzędzi i ustawienia wsparcia prawda zrobiona proszę o pomoc
Harsha

<item name = "windowActionModeOverlay"> true </item> działało zgodnie z oczekiwaniami!
Francois

8

Rozwiązanie Jacoba działało dla mnie, ale kontekstowy pasek ActionBar był przezroczysty, a pasek narzędzi widoczny przez niego. Można to rozwiązać w następujący sposób:

<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>

Motyw „AppTheme.Base” musi być tym, który jest zastosowany do paska narzędzi.

Więcej szczegółów dotyczących kontekstowego stylu ActionBar:

jak dostosować kontekstowy pasek akcji za pomocą appCompat w projektowaniu materiałów


0

Bardzo przydatna metoda przeniesienia paska narzędzi na pierwszy plan toolbar.bringToFront()


2
View.bringToFront()jest bardzo ciężką operacją i ogólnie należy jej unikać za wszelką cenę.
dominus

Masz rację, ale animacja np. Od góry do dołu ekranu zachodzi na pasek narzędzi. Dlatego musimy użyć toolbar.bringToFront (), aby animować poniżej paska narzędzi. Jeśli istnieje jakiś alternatywny sposób, aby udostępnić
:)

0

Kolejny mały dodatek: upewnij się, że ustawiłeś przynajmniej pusty ekran w aktywności poprzez setContentView(R.layout.empty_screen)załadowanie całego interfejsu użytkownika we fragmentach ( ft.replace(android.R.id.content, fragment)).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.