Barra de ferramentas e ActionBar contextual com AppCompat-v7

182

Estou trabalhando no uso da barra de ferramentas recém-adicionada que foi introduzida no Lollipop e na biblioteca AppCompat-v7. eu segui este guia sobre a configuração da barra de ferramentas. Observei que, quando você invoca algo que abrirá a ActionBar contextual (como realçar o texto para copiar / colar), ele empurrará a barra de ferramentas para baixo na página. Você pode ver o que estou falando na imagem na parte inferior da página:

Então, essencialmente, eu configurei assim. Eu tenho a barra de ferramentas definida em um arquivo xml que eu uso com tags de inclusão:

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

Em seguida, instanciamo-o em minha opinião:

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

No código, eu configurei assim:

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

Alguém sabe como fazer isso para que a ActionBar contextual chegue ao topo da barra de ferramentas?

Barra de ferramentas e ActionBar contextual

ariets
fonte
Qual tema sua atividade está usando?
alanv
David, apenas cliquei no link e parece estar funcionando para mim.
Ariets

Respostas:

320

Atualizar:

Solução: use a propriedade windowActionModeOverlay . Defina isso no seu tema:

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

e o modo de ação será mostrado sobre a barra de ação em vez de pressioná-lo. (Se você não estiver usando o AppCompat mais recente, precisará adicionar o prefixo "android:" à propriedade). Basicamente, permite ao AppCompat saber que você tem uma barra de ferramentas localizada na parte superior da tela e que ela deve desenhar o ActionMode sobre ela.


Resposta antiga / solução alternativa:

Eu tive o mesmo problema. Independentemente do tema definido, ele sempre pressiona a barra de ferramentas que defini como ActionBar. Eu tentei com e sem a biblioteca de suporte, mas isso não importava.

Infelizmente, não consegui corrigi-lo, então criei uma solução alternativa. Nos meus ActionModeCallback, onCreateActionModeescondo a barra de ação:

actionBarToolbar.setVisibility(View.GONE);

e onDestroyActionModeeu mostro novamente:

actionBarToolbar.setVisibility(View.VISIBLE);

A ocultação / exibição acontece tão rapidamente que não é perceptível nos meus dispositivos de teste. É claro que há uma desvantagem: embora a animação de entrada ainda funcione, a animação de saída da barra de ação contextual se perde porque a Barra de Ferramentas aparece imediatamente sobre ela. Mas até encontrarmos uma solução melhor, acho que estamos presos a isso.


(Minha atividade, na verdade, está estendendo uma BaseActivityclasse personalizada que possui um método chamado getActionBarToolbar(), extraído do código-fonte do aplicativo Google I / O 2014 , para que eu possa facilmente buscar a Barra de Ferramentas:

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

Pena que o aplicativo de E / S não use a barra de ação contextual.)

Jacob Ras
fonte
Sim, essa foi a única solução que eu pude encontrar também. No entanto, há casos em que a ActionBar contextual acontece no sistema (por exemplo, em um WebView ou com um EditText). Aqueles para os quais você não recebe os retornos de chamada. Então, como você mostraria / ocultaria isso? (Ou estou errado e você pode, de fato, receber os retornos de chamada do CAB com eles)?
Ariets # 19/14
1
Sim, você pode TextView.setCustomSelectionActionModeCallback () para isso, como Aleksandar descrito em sua resposta.
Jacob Ras
1
Ah, já não é possível atualizar meu comentário. Pequena adição: parece que setCustomSelectionActionModeCallback não pode ser usado com o ActionModeCallback da biblioteca de suporte. Estou usando uma verificação VERSION.SDK_INT para defini-la. Ainda é necessário testar se o problema também ocorre em dispositivos pré-Honeycomb.
Jacob Ras
@ariets, veja minha resposta atualizada. Eu me sinto um lixo pouco por ter esquecido completamente que a propriedade, mas pelo menos podemos nos livrar da solução agora ;-)
Jacob Ras
1
Engraçado eu estou usando a mais recente (compilação 'com.android.support:appcompat-v7:22.0.0'), mas eu tenho que deixar de fora o android: parte para que ele funcione ...
Warpzit
16

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

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

e você tem que usar

<item name="windowActionModeOverlay">true</item>
Frank
fonte
para mim, ele faz para android.support.v7.app.ActionBar
Frank
Eu recebo este erro-> startActionMode (android.view.ActionMode.Callback) no modo de exibição não pode ser aplicado a (android.support.v7.view.ActionMode.Callback)
Faheem
Ah ok. Minha versão mínima não é menor que 11. Para que eu possa usar um android.view.ActionMode. Retorno de chamada em uma barra de ferramentas android.support.v7.widget. nunca usei android.support.v7.view.ActionMode.Callback.
Frank
Vale a pena mencionar AppCompatActivity.startSupportActionMode(callback) , para obter compatibilidade com atributos como app:iconTintno item xmls do menu.
geekley
14

Apenas uma pequena adição: para

<item name="windowActionModeOverlay">true</item>
Para trabalhar, é importante ligar super.onCreate(savedInstanceState) ANTES de ligar setContentView(R.layout.your_activity)em sua atividade. Realmente faz diferença neste caso!

Daniel Veihelmann
fonte
11

No meu caso, <item name="windowActionModeOverlay">true</item>não funcionou, mas este trabalho:, <item name="android:windowActionModeOverlay">true</item>a androidé a chave.

Jenkyn
fonte
8
Você usa <item name="windowActionModeOverlay">true</item>com a barra de ferramentas appcompat, caso contrário, usa o androidespaço para nome.
Javier Mendonça
não usar para mim na minha barra de ferramentas adicionando disposição am, na atividade initialize barra de ferramentas e setsupport verdadeiro feito ajuda por favor me
Harsha
<item name = "windowActionModeOverlay"> true </item> funcionou como esperado!
Francois
8

A solução de Jacob funcionou para mim, mas a ActionBar contextual era transparente e a Barra de Ferramentas visível através dela. Isso pode ser resolvido da seguinte maneira:

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

O tema "AppTheme.Base" deve ser o aplicado à barra de ferramentas.

Mais detalhes sobre o estilo contextual do ActionBar:

como personalizar a barra de ação contextual usando appCompat no design de materiais

Pete
fonte
0

Método muito útil para colocar a barra de ferramentas na frente toolbar.bringToFront()

kunal.c
fonte
2
View.bringToFront()é uma operação muito pesada e geralmente deve ser evitada a qualquer custo.
dominus
Você está certo, mas a animação, por exemplo, de cima para baixo da tela, se sobrepõe à barra de ferramentas. Por isso, precisamos usar toolbar.bringToFront () para animar abaixo toolbar.If houver qualquer maneira alternativa você pode compartilhar:)
kunal.c
0

Outra pequena adição: defina pelo menos uma tela vazia na atividade via setContentView(R.layout.empty_screen)se você carregar a interface do usuário inteira em fragmentos ( ft.replace(android.R.id.content, fragment)).

Andreas Wenger
fonte