Exibir ActionMode na barra de ferramentas

87

Estou tentando usar o android.view.ActionModecom o novo android.support.v7.widget.Toolbar, além do tradicional android.app.ActionBar. Consigo exibi-lo com:

toolbar.startActionMode(callback);

O problema é que o ActionModeé exibido sobre o ActionBare não sobre o Toolbar. Existe uma maneira de mudar isso?

Tentei definir o seguinte no meu tema, mas não parece mudar nada:

<item name="windowActionModeOverlay">true</item>
Gaëtan
fonte
1
Acho que ActionMode é parte da ActionBar e você não pode mudar sua posição
SpyZip
Isso é ruim. Obrigado pela resposta
Gaëtan,
1
Você definiu a barra de ferramentas como barra de ação?
Nikola Despotoski
1
ainda tem o mesmo problema, alguma atualização sobre isso? Eu tenho a mesma situação, uma barra de ferramentas como a barra de ação clássica, e uma barra de ferramentas abaixo, como cabeçalho e menu de opções para o conteúdo mostrado abaixo. enfrentando este problema e não é capaz de mover o modo de ação para baixo.
cV2

Respostas:

82

Como você está usando o Toolbar, também presumo que esteja usando o AppCompatActivitye substituiu o integrado ActionBarpor seu personalizado Toolbarusando setSupportActionBar(toolbar);

Em primeiro lugar, certifique-se de que está importando o namespace correto:

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

e não

import android.view.ActionMode;

então use

_actionMode = startSupportActionMode(this);

e não

_actionMode = startActionMode(this);
Kuffs
fonte
35
Isso mais a windowActionModeOverlayconfiguração funcionou para mim.
Jimeux
4
Atualmente estou usando AppCompatActivitye adicionando windowActionModeOverlay foi o suficiente para mim. Tentei usar o import android.support.v7.view.ActionModemas não funcionou MultiChoiceModeListener, então acabei usando android.view.ActionMode. Você sabe se existe uma versão compatível do MultiChoiceModeListener? Obrigado
Axel
Existe uma versão compatível com MultiChoiceModeListener?
galaxigirl,
@galaxigirl, não parece que existe. Você tem que lidar com os eventos de clique em seu adaptador e visualizar holderr
peterchaula
67

Não o inicie na sua atividade, mas na sua barra de ferramentas. Em sua atividade:

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

e você tem que usar

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

em seu tema, conforme afirmado por Andre.

Frank
fonte
1
Isso funcionou para mim, porque eu também tinha um requisito especial. Em vez de implementar ActionMode.Callback, eu queria implementar MultiChoiceModeListener. O problema de usar o suporte ActionModeé que não parece haver uma versão de suporte do MultiChoiceModeListener.
jwir3
43

Experimente isso em seu tema:

<item name="windowActionModeOverlay">true</item>
André Restivo
fonte
Conforme afirmado na minha pergunta, já tentei fazer isso sem sucesso. Mas obrigado!
Gaëtan
Desculpe, não sabia que você já havia tentado. Tem certeza que não funciona? Funciona para mim.
André Restivo
Tive o mesmo problema e isso resolve. Obrigado!
Marta Rodriguez
2
Tentei com e sem o android:prefixo e coloquei-o no tema do meu aplicativo. As ActionModesobreposições são ActionBar, mas eu quero sobre as minhas Toolbar, que estão abaixo de ActionBar.
Gaëtan
@Gaëtan Você obteve uma resposta para isso? Estou tendo o mesmo problema e estou estendendo Activity e não AppCompatActivity, pois meu aplicativo suporta API 21 e superior.
SjDev
14

Acho que a única coisa que as pessoas não estão deixando claro é que a linha

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

é colocado no tema Base, ou seja, AppTheme e não 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" />

Canhoto
fonte
Essa foi a única mudança que eu precisava. Obrigado!
PNDA
5

encontre seu AndroidManifest.xml, em seguida, adicione o código abaixo em seu aplicativo ou tema de atividade

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

assim como:

<style name="WorkTimeListTheme" parent="AppTheme.NoActionBar">
        <item name="windowActionModeOverlay">true</item>
        <item name="actionModeBackground">@color/theme_primary</item>
    </style>
Zhangjin
fonte
1

Esta é a solução que fiz.

No meu método onCreateActionMode de ActionMode.Callback , adiciono isto:

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

Funciona para mim.

Avery
fonte
1

Eu tentei todos os métodos acima, mas ainda não funcionou. E então, tentei o método abaixo:

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

Aqui, usei o modo de ação e o método startSupportActionMode da biblioteca de suporte. Ao mesmo tempo, também tentei modificar o tema de determinada atividade. Certamente, não funciona. Então, se você realmente não tem escolha melhor, você pode tentar este.

Recentemente, descobri que usei o quadro Colorido para habilitar vários temas do meu aplicativo, isso mudará o tema no código. Quando tentei modificar o estilo neste framework, ele funcionou.

Espero que funcione.

Jeff Wong
fonte
Esta é a única coisa que funcionou para mim. Muito obrigado.
Rachit
0

Se você vir a árvore de visualização, poderá escrever o código abaixo:

 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
fonte