Barre d'outils et ActionBar contextuelle avec AppCompat-v7


182

Je travaille sur l'utilisation de la barre d'outils nouvellement ajoutée qui a été introduite dans Lollipop et la bibliothèque AppCompat-v7. J'ai suivi ce guide sur la configuration de la barre d'outils, j'ai remarqué que lorsque vous appelez quelque chose qui fera apparaître la barre d'action contextuelle (comme la mise en évidence du texte pour copier / coller), cela poussera la barre d'outils vers le bas sur la page. Vous pouvez voir de quoi je parle dans l'image en bas de page:

Donc, essentiellement, je l'ai mis en place comme ça. J'ai la barre d'outils définie dans un fichier xml que j'utilise avec des balises include:

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

Ensuite, je l'instancie à mon avis:

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

Dans le code, je l'ai configuré comme ceci:

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

Quelqu'un sait-il comment faire pour que la barre d'action contextuelle vienne au-dessus de la barre d'outils?

Barre d'outils et barre d'action contextuelle


Quel thème utilise votre activité?
alanv

David, je viens de cliquer sur le lien et cela semble fonctionner pour moi.
ariets

Réponses:


320

Mise à jour:

Solution: utilisez la propriété windowActionModeOverlay . Définissez ceci dans votre thème:

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

et le mode d'action sera affiché sur la barre d'action au lieu de le pousser vers le bas. (Si vous n'utilisez pas le dernier AppCompat, vous devez ajouter le préfixe "android:" à la propriété). Cela permet essentiellement à AppCompat de savoir que vous avez une barre d'outils située en haut de l'écran et qu'il doit dessiner le ActionMode dessus.


Ancienne réponse / solution de contournement:

J'ai rencontré le même problème. Quel que soit le thème que j'ai défini, il abaisse toujours la barre d'outils que j'ai définie comme ActionBar. J'ai essayé avec et sans la bibliothèque de support, mais cela n'avait pas d'importance.

Malheureusement, je n'ai pas pu le réparer, j'ai donc créé une solution de contournement. Dans mon ActionModeCallback's onCreateActionModeje cache la barre d'action:

actionBarToolbar.setVisibility(View.GONE);

et dans onDestroyActionModeje le montre à nouveau:

actionBarToolbar.setVisibility(View.VISIBLE);

Le masquage / affichage se produit si rapidement qu'il n'est pas perceptible sur mes appareils de test. Il y a bien sûr un inconvénient: bien que l'animation d'entrée fonctionne toujours, l'animation de sortie de la barre d'action contextuelle est perdue car la barre d'outils apparaît immédiatement dessus. Mais jusqu'à ce que nous trouvions une meilleure solution, je suppose que nous sommes coincés avec cela.


(Mon activité étend en fait une BaseActivityclasse personnalisée qui a une méthode appelée getActionBarToolbar(), tirée du code source de l'application Google I / O 2014 , afin que je puisse facilement récupérer la barre d'outils:

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

Dommage que l'application d'E / S n'utilise pas la barre d'action contextuelle.)


Ouais, c'était la seule solution à laquelle je pouvais aussi arriver. Cependant, il existe des cas où la barre d'action contextuelle provient du système (par exemple dans une WebView ou avec un EditText). Ceux pour lesquels vous ne recevez pas les rappels. Alors, comment feriez-vous pour le montrer / le cacher pour cela? (Ou ai-je tort et vous pouvez, en fait, obtenir les rappels pour le CAB avec ceux-ci)?
ariets

1
Oui, vous pouvez TextView.setCustomSelectionActionModeCallback () pour cela, comme Aleksandar décrit dans sa réponse.
Jacob Ras

1
Oh, je ne peux déjà plus mettre à jour mon commentaire. Petit ajout: il semble que setCustomSelectionActionModeCallback ne puisse pas être utilisé avec le ActionModeCallback de la bibliothèque de support. J'utilise un chèque VERSION.SDK_INT pour le définir. Encore faut-il tester si le problème se produit également sur les périphériques pré-Honeycomb.
Jacob Ras

@ariets s'il vous plaît voir ma réponse mise à jour. Je me sens un peu vide d'avoir complètement oublié cette propriété, mais au moins nous pouvons nous débarrasser de la solution de contournement maintenant ;-)
Jacob Ras

1
Drôle, j'utilise la dernière version (compilez 'com.android.support:appcompat-v7:22.0.0') mais je dois laisser de côté l'android: une partie pour que cela fonctionne ...
Warpzit

16

Ne le lancez pas sur votre activité, mais sur votre barre d'outils. Dans votre activité:

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

et vous devez utiliser

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

pour moi, il le fait pour android.support.v7.app.ActionBar
Frank

J'obtiens cette erreur-> startActionMode (android.view.ActionMode.Callback) dans View ne peut pas être appliquée à (android.support.v7.view.ActionMode.Callback)
Faheem

Ah ok. Ma version minimale n'est pas inférieure à 11. Je peux donc utiliser un android.view.ActionMode. Rappel sur un android.support.v7.widget.Toolbar, je n'ai jamais utilisé android.support.v7.view.ActionMode.Callback.
Frank

Cela vaut la peine de mentionner AppCompatActivity.startSupportActionMode(callback), pour obtenir la compatibilité avec des attributs comme app:iconTintdans l'élément de menu xmls.
geekley

14

Juste un petit ajout: pour

<item name="windowActionModeOverlay">true</item>
pour travailler, il est important d'appeler super.onCreate(savedInstanceState) AVANT d' appeler setContentView(R.layout.your_activity)votre activité. Cela fait vraiment une différence dans ce cas!


11

Dans mon cas, <item name="windowActionModeOverlay">true</item>ne fonctionne pas, mais ce travail: <item name="android:windowActionModeOverlay">true</item>la androidest la clé.


8
Vous utilisez <item name="windowActionModeOverlay">true</item>avec la barre d'outils appcompat, sinon vous utilisez l' androidespace de noms.
Javier Mendonça

aucune utilité pour moi dans ma mise en page j'ajoute une barre d'outils, dans l'activité initialiser la barre d'outils et setsupport true done s'il vous plaît aidez-moi
Harsha

<item name = "windowActionModeOverlay"> true </item> a fonctionné comme prévu!
François

8

La solution de Jacob a fonctionné pour moi, mais l'ActionBar contextuelle était transparente et la barre d'outils visible à travers. Cela peut être résolu comme suit:

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

Le thème "AppTheme.Base" doit être celui appliqué à la barre d'outils.

Plus de détails sur le style contextuel d'ActionBar:

comment personnaliser la barre d'actions contextuelles à l'aide de appCompat dans la conception de matériaux


0

Méthode très utile pour mettre la barre d'outils au premier plan toolbar.bringToFront()


2
View.bringToFront()est une opération très lourde et doit généralement être évitée à tout prix.
dominus

Vous avez raison, mais pour l'animation par exemple de haut en bas de l'écran chevauchera la barre d'outils. Par conséquent, nous devons utiliser toolbar.bringToFront () pour animer ci-dessous la barre d'outils.S'il existe un autre moyen de partager
:)

0

Autre petit ajout: assurez-vous de définir au moins un écran vide dans l'activité via setContentView(R.layout.empty_screen)si vous chargez toute l'interface utilisateur dans fragments ( ft.replace(android.R.id.content, fragment)).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.