Wyświetl ActionMode na pasku narzędzi

87

Staram się korzystać android.view.ActionModez nowego android.support.v7.widget.Toolbar, oprócz tradycyjnego android.app.ActionBar. Mogę to wyświetlić za pomocą:

toolbar.startActionMode(callback);

Problem polega na tym, że ActionModejest wyświetlany nad ActionBar, a nie nad Toolbar. Czy jest sposób, aby to zmienić?

Próbowałem ustawić następujący motyw w moim motywie, ale wydaje się, że nic to nie zmienia:

<item name="windowActionModeOverlay">true</item>
Gaëtan
źródło
1
Myślę, że ActionMode jest częścią ActionBar i nie możesz zmienić jego pozycji
SpyZip
Szkoda. Dzięki za odpowiedź
Gaëtan
1
Czy ustawiłeś pasek narzędzi jako pasek akcji?
Nikola Despotoski
1
nadal masz ten sam problem, jakieś aktualizacje? Mam taką samą sytuację, jeden pasek narzędzi jak klasyczny pasek akcji i jeden pasek narzędzi poniżej, jako nagłówek i menu opcji dla zawartości pokazanej poniżej. staje przed tym problemem i nie jest w stanie obniżyć trybu działania.
cV2

Odpowiedzi:

82

Ponieważ używasz programu Toolbar, zakładam również, że używasz AppCompatActivityi zastąpiłeś wbudowaną ActionBarniestandardową Toolbarmetodą setSupportActionBar(toolbar);

Przede wszystkim upewnij się, że importujesz poprawną przestrzeń nazw:

import androidx.appcompat.view.ActionMode;
// Or
import android.support.v7.view.ActionMode;

i nie

import android.view.ActionMode;

następnie użyj

_actionMode = startSupportActionMode(this);

i nie

_actionMode = startActionMode(this);
Kufki
źródło
35
To plus windowActionModeOverlayustawienie działało dla mnie.
Jimeux
4
Obecnie używam AppCompatActivityi windowActionModeOverlay wystarczyło mi dodanie . Próbowałem użyć importu, android.support.v7.view.ActionModeale to nie działało MultiChoiceModeListener, więc android.view.ActionModezamiast tego użyłem . Czy wiesz, czy istnieje wersja obsługująca MultiChoiceModeListener? Dzięki
Axel
Czy istnieje obsługiwana wersja MultiChoiceModeListener?
galaxigirl
@galaxigirl, chyba nie ma. Musisz obsłużyć zdarzenia kliknięcia w swoim adapterze i wyświetlić holderr
peterchaula
67

Nie uruchamiaj go na swojej aktywności, ale na pasku narzędzi. W Twojej działalności:

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

i musisz użyć

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

w twoim motywie, jak stwierdził Andre.

Szczery
źródło
1
To zadziałało dla mnie, ponieważ miałem też specjalne wymagania. Zamiast wdrażać ActionMode.Callback, chciałem wdrożyć MultiChoiceModeListener. Problem z korzystaniem z pomocy technicznej ActionModepolega na tym, że nie ma wersji obsługującej MultiChoiceModeListener.
jwir3
43

Spróbuj tego w swoim motywie:

<item name="windowActionModeOverlay">true</item>
André Restivo
źródło
Jak stwierdzono w moim pytaniu, próbowałem tego już bez powodzenia. Ale dziękuję!
Gaëtan
Przepraszam, nie zdawałem sobie sprawy, że już tego próbowałeś. Czy na pewno to nie działa? Mi to pasuje.
André Restivo
Miałem ten sam problem i to go rozwiązuje. Dzięki!
Marta Rodriguez
2
Próbowałem z android:prefiksem i bez niego i umieściłem go w motywie aplikacji. ActionModePrzykrywa ActionBar, ale chcę ją nad moim Toolbar, który jest poniżej ActionBar.
Gaëtan
@ Gaëtan Czy otrzymałeś na to odpowiedź? Mam ten sam problem i rozszerzam Activity, a nie AppCompatActivity, ponieważ moja aplikacja obsługuje API 21 i nowsze.
SjDev,
15

Myślę, że jedyną rzeczą, której ludzie nie wyjaśniają, jest linia

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

jest umieszczony w motywie podstawowym, tj. AppTheme, a nie AppTheme.NoActionBar

<resources>

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="windowActionModeOverlay">true</item>
</style>

<style name="transparent" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowIsTranslucent">true</item>
</style>


<style name="AppTheme.NoActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
</style>

<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

Leworęczny
źródło
To była jedyna zmiana, której potrzebowałem. Dzięki!
PNDA
5

znajdź swój AndroidManifest.xml, a następnie dodaj poniższy kod w swojej aplikacji lub motywie działania

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

tak jak:

<style name="WorkTimeListTheme" parent="AppTheme.NoActionBar">
        <item name="windowActionModeOverlay">true</item>
        <item name="actionModeBackground">@color/theme_primary</item>
    </style>
zhangjin
źródło
1

To jest rozwiązanie, które stworzyłem.

W mojej metodzie onCreateActionMode klasy ActionMode.Callback dodaję to:

StandaloneActionMode standaloneActionMode = (StandaloneActionMode) actionMode;
Field mContextView;
try {
     mContextView = StandaloneActionMode.class.getDeclaredField("mContextView");
     mContextView.setAccessible(true);
     View contextView = (View) mContextView.get(standaloneActionMode);
     MarginLayoutParams params = (MarginLayoutParams) contextView.getLayoutParams();
     params.topMargin = mToolbar.getTop();
  } catch (NoSuchFieldException e) {
            e.printStackTrace();
  } catch (IllegalAccessException e) {
            e.printStackTrace();
  } catch (IllegalArgumentException e) {
            e.printStackTrace();
  }

Mi to pasuje.

Avery
źródło
1

Wypróbowałem wszystkie powyższe metody, ale nadal nie działają. A potem wypróbowałem poniższą metodę:

    private class ActionModeCallback implements ActionMode.Callback {
    @Override
    public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
        actionMode.getMenuInflater().inflate(R.menu.note_find_action, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
        ((AppCompatActivity) getActivity()).getSupportActionBar().hide();
        return false;
    }

    @Override
    public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
        return false;
    }

    @Override
    public void onDestroyActionMode(ActionMode actionMode) {
        ((AppCompatActivity) getActivity()).getSupportActionBar().show();
    }
}

Tutaj użyłem trybu akcji i metody startSupportActionMode biblioteki wsparcia. Jednocześnie starałem się również zmodyfikować temat danej czynności. Na pewno to nie działa. Więc jeśli naprawdę nie masz lepszego wyboru, możesz spróbować tego.

Niedawno odkryłem, że użyłem kolorowej ramki, aby włączyć wiele motywów mojej aplikacji, co zmieni motyw w kodzie. Kiedy próbowałem zmodyfikować styl w tych ramach, to działa.

Mam nadzieję, że to działa.

Jeff Wong
źródło
To jedyna rzecz, która zadziałała dla mnie. Wielkie dzięki.
Rachit
0

Jeśli zobaczysz drzewo widoków, możesz napisać poniższy kod:

 ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
    traverseView(decorView);
 /**
 * traverse find actionmodebar
 * @param root  view
 */
public void traverseView(View root) {
    if (root==null){
        return;
    }
    if (root instanceof ActionBarContextView){
        root.setVisibility(View.GONE);
        return;
    }
    if ((root instanceof ViewGroup)) { // If view is ViewGroup, apply this method on it's child views
        ViewGroup viewGroup = (ViewGroup) root;
        for (int i = 0; i < viewGroup.getChildCount(); ++i) {
            traverseView(viewGroup.getChildAt(i));
        }
    }
}
user2416658
źródło
0

Tak więc, po wielu dniach spędzonych przez ten wątek, w końcu udało mi się to. Chciałbym podsumować to, co zrobiłem.

Uwaga: Jest to rozwiązanie wykorzystujące Toolbarzastąpić domyślne ActionBarw AppCompatActivity.

  1. Dodałem tę linię do my AppTheme: Mówi androidowi, że chcesz, aby twój tryb akcji nakładał się na pasek narzędzi
<item name="windowActionModeOverlay">true</item>
  1. Użyj odpowiedniego importu:

Musisz użyć tych importów, aby pracować z AppCompatActivity:

import androidx.appcompat.view.ActionMode;
// or
import android.support.v7.view.ActionMode;
  1. Uruchom ActionMode na swojej aktywności w następujący sposób:
actionMode = startSupportActionMode(callback);

A nie tak:

actionMode = startActionMode(callback);

You Activity automatycznie tworzy ActionMode na pasku narzędzi, ponieważ jest ustawiony jako supportActionToolbar. Styl traktuje dsiplaying jako nakładkę.

Dzięki @Kuffs i @Lefty.

Leon Latsch
źródło