Aucune ombre par défaut sur la barre d'outils?


165

Je mets à jour mon application avec la nouvelle barre d'outils de la bibliothèque de support v21. Mon problème est que la barre d'outils ne projette aucune ombre si je ne règle pas l'attribut "élévation". Est-ce le comportement normal ou je fais quelque chose de mal?

Mon code est:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical">

   <android.support.v7.widget.Toolbar
       xmlns:app="http://schemas.android.com/apk/res-auto"
       android:id="@+id/my_awesome_toolbar"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:background="?attr/colorPrimary"
       android:elevation="4dp"
       android:minHeight="?attr/actionBarSize"
       app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
       app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

   <FrameLayout
       android:id="@+id/FrameLayout1"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       .
       .
       .

Et dans mon activité - méthode OnCreate:

    Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
    setSupportActionBar(toolbar);

Le voyez-vous sur un appareil exécutant Lollipop?
rlay3

3
Sur un appareil exécutant Lollipop, l'ombre est affichée en raison de l'attribut d'élévation, mais pas sur KitKat ou les versions antérieures. C'est le comportement attendu pour l'attribut d'élévation comme le dit la documentation, mais je m'attendais à ce que, par défaut sans l'attribut d'élévation, l'ombre soit projetée comme elle le fait dans la barre d'action sur chaque version.
MrBrightside

J'ai posté une solution possible ici: stackoverflow.com/a/26759202/553905
Billy

Utilisez les dossiers / values ​​et styles.xml pour appliquer le code shadow approprié en fonction de la version du système d'exploitation (voir ci-dessous).
radley

Réponses:


252

J'ai fini par définir ma propre ombre portée pour la barre d'outils, j'ai pensé que cela pourrait être utile pour ceux qui la recherchent:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="top"
              android:orientation="vertical">

    <android.support.v7.widget.Toolbar android:id="@+id/toolbar"
                                       android:layout_width="match_parent"
                                       android:layout_height="wrap_content"
                                       android:background="@color/color_alizarin"
                                       android:titleTextAppearance="@color/White"
                                       app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

    <FrameLayout android:layout_width="match_parent"
                 android:layout_height="match_parent">

        <!-- **** Place Your Content Here **** -->

        <View android:layout_width="match_parent"
              android:layout_height="5dp"
              android:background="@drawable/toolbar_dropshadow"/>

    </FrameLayout>

</LinearLayout>

@ drawable / toolbar_dropshadow:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
       android:shape="rectangle">

    <gradient android:startColor="@android:color/transparent"
              android:endColor="#88333333"
              android:angle="90"/>

</shape>

@ couleur / color_alizarine

<color name="color_alizarin">#e74c3c</color>

entrez la description de l'image ici


3
N'oubliez pas de masquer votre vue si l'appareil que vous utilisez est> = à Lollipop, sinon vous vous retrouverez avec deux ombres.
mradzinski

1
Ce n'est pas la bonne façon d'y arriver car vous devrez supprimer cette vue pour les mises en page 5.0. Utilisez plutôt android: windowContentOverlay ou android: premier plan.
radley

3
De Google à propos de la conception du matériau de la barre d'outils , vous devez définir android:layout_height="4dp"la hauteur de l'ombre, au lieu de 5dp. En fait, l'élévation est la même que la hauteur de l'ombre que vous avez définie FrameLayout.
Anggrayudi H

2
J'ai des problèmes avec cette solution car je gonfle la mise en page de mes activités dans la mise en page du cadre de votre exemple, pouvez-vous penser à un moyen pour que cela fonctionne?
Zach Sperske

2
Recommander d'utiliser "android: endColor =" # c7c7c7 "sur android: endColor =" # 88333333 "
Mohammad Faisal

211

Google a publié la bibliothèque Design Support il y a quelques semaines et il existe une solution astucieuse à ce problème dans cette bibliothèque.

Ajoutez la bibliothèque Design Support en tant que dépendance dans build.gradle:

compile 'com.android.support:design:22.2.0'

Ajoutez AppBarLayoutfourni par la bibliothèque comme enveloppe autour de votre Toolbarmise en page pour générer une ombre portée.

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
       <android.support.v7.widget.Toolbar
           .../>
    </android.support.design.widget.AppBarLayout>

Voici le résultat:

entrez la description de l'image ici

Il existe de nombreuses autres astuces avec la bibliothèque de support de conception.

  1. http://inthecheesefactory.com/blog/android-design-support-library-codelab/en
  2. http://android-developers.blogspot.in/2015/05/android-design-support-library.html

AndroidX

Comme ci-dessus mais avec dépendance:

implementation 'com.google.android.material:material:1.0.0'

et com.google.android.material.appbar.AppBarLayout


26
Définir le AppBarLayoutcomme un wrapper autour de Toolbarne définit aucune ombre pour moi. Notez que je n'utilise pas de tiroir de navigation. Des idées sur pourquoi cela ne fonctionne pas?
avb

@ avb1994 Je ne peux pas le dire avec certitude, je l'ai testé sans tiroir de navigation. Pouvez-vous le poster sous forme de question avec le fichier de mise en page?
Binoy Babu le

voir ma question: stackoverflow.com/questions/31115531/ ... merci pour votre commentaire
avb

2
Vous n'avez pas besoin de ces deux lignes pour compiler 'com.android.support:support-v4:22.2.0' compile 'com.android.support:appcompat-v7:22.2.0', car compilez 'com.android.support: design: 22.2.0 'dépend d'eux
Andrey

8
Notez que cela ne fonctionne que pour la sucette et au-dessus. Cela ne fonctionnera pas avant sucette car en dessous, il utilise simplement ViewCompat.setElevation ().
Amirul Zin

25

Vous ne pouvez pas utiliser l'attribut d'élévation avant l'API 21 (Android Lollipop). Vous pouvez cependant ajouter l'ombre par programme, par exemple en utilisant une vue personnalisée placée sous la barre d'outils.

@ layout / toolbar

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/blue"
    android:minHeight="?attr/actionBarSize"
    app:theme="@style/ThemeOverlay.AppCompat.ActionBar" />

<View
    android:id="@+id/toolbar_shadow"
    android:layout_width="match_parent"
    android:layout_height="3dp"
    android:background="@drawable/toolbar_dropshadow" />

@ drawable / toolbar_dropshadow

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <gradient
        android:startColor="@android:color/transparent"
        android:endColor="#88333333"
        android:angle="90"/> </shape>

dans votre plan d'activité <include layout="@layout/toolbar" />

entrez la description de l'image ici


2
Pouvez-vous corriger l' @layout/toolbarexemple avec le fichier de mise en page complet?
Daniel Gomez Rico

1
Pourquoi @ layout / toolbar a-t-il deux vues racine? Pouvez-vous donner l'exemple complet s'il vous plaît?
RED_

18

Utilisez les dossiers / values pour appliquer le style d'ombre correct en fonction de la version du système d'exploitation.

Pour les appareils sous 5.0 , utilisez /values/styles.xml pour ajouter windowContentOverlay au corps de votre activité:

<style name="MyViewArea">
    <item name="android:foreground">?android:windowContentOverlay</item>
</style>

<style name="MyToolbar">
    <item name="android:background">?attr/colorPrimary</item>
</style>

Ajoutez ensuite votre propre ombre personnalisée en modifiant votre thème pour inclure:

<item name="android:windowContentOverlay">@drawable/bottom_shadow</item>

Vous pouvez récupérer la ressource d'ombre d'application IO de Google ici: https://github.com/google/iosched/blob/master/android/src/main/res/drawable-xxhdpi/bottom_shadow.9.png

Pour les appareils 5.0 et plus récents , utilisez /values-v21/styles.xml pour ajouter une élévation à votre barre d'outils à l'aide d'un style d'en-tête personnalisé:

<style name="MyViewArea">
</style>

<style name="MyToolbar">
    <item name="android:background">?attr/colorPrimary</item>
    <item name="android:elevation">4dp</item>
</style>

Notez que dans le second cas, j'ai dû créer un style MyViewArea vide pour que windowContentOverlay n'apparaisse pas également.

[Mise à jour: modification des noms de ressources et ajout de Google Shadow.]


Puis-je savoir ce que sont MyBody et MyHeader? Où dois-je les appliquer?
Cheok Yan Cheng

J'ai mis à jour les noms: MyHeader est maintenant MyToolbar et MyBody est MyViewArea. Vous pouvez attribuer des styles dans des mises en page XML comme ceci: style = "@ style / MyToolbar".
radley

À quoi s'applique MyViewArea?
Zach Sperske

Votre page / corps / zone d'affichage.
radley

Je pense android:foregroundque cela ne fonctionne que sur FrameLayout avant l'API 23.
androidguy

14

Cela a très bien fonctionné pour moi:

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/primary"
    card_view:cardElevation="4dp"
    card_view:cardCornerRadius="0dp">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/primary"
        android:minHeight="?attr/actionBarSize" />

</android.support.v7.widget.CardView>

Comment cela peut-il fonctionner si sur les pads pré-sucette cardview lui-même afin de dessiner l'ombre? Voici ce que j'obtiens: i.imgur.com/BIj8env.png cette réponse a fonctionné pour moi et elle ne souffre pas des inconvénients de celle-ci: stackoverflow.com/questions/26575197/...
Aspiring Dev

2
En fait, vous êtes mieux avec l'AppBarLayout comme dans cette réponse stackoverflow.com/a/31026359/1451716 Ma réponse est ancienne, avant la publication de l'AppBarLayout
Islam A. Hassan

Est-ce même légal? Il n'est pas censé être utilisé avec la barre d'outils. OMG!
user155

12

Si vous définissez ToolBarcomme, ActionBarappelez simplement:

getSupportActionBar().setElevation(YOUR_ELEVATION);

Remarque: il doit être appelé après setSupportActionBar(toolbar);


1
Est-ce juste moi, ou le tiroir de navigation réinitialise-t-il l'élévation de la barre d'outils? J'ai essayé de le définir sur 0, et cela a fonctionné, mais quand je fais glisser le tiroir de navigation, je vois qu'il a à nouveau une ombre ...
développeur android

6
setElevation()est défini uniquement pour l'API-21 +.
Subin Sebastian

@Sebastian L'élévation de la barre d'actions de support fonctionne également pour les API précédentes.
Roberto B.

2
En interne, cela utilise ViewCompat.setElevation()et ne fonctionnera donc que sur l'API 21 et plus.
botteaap le

Utilisez android: windowContentOverlay ou android: premier plan pour sous l'API 21.
radley

9

J'ai ajouté

<android.support.v7.widget.Toolbar
...
android:translationZ="5dp"/>

dans la description de la barre d'outils et cela fonctionne pour moi. Utilisation de 5.0+


7

Mon problème est que la barre d'outils ne projette aucune ombre si je ne règle pas l'attribut "élévation". Est-ce le comportement normal ou je fais quelque chose de mal?

C'est le comportement normal. Consultez également la FAQ à la fin de cet article .


7

J'ai joué avec ça pendant des heures, voici ce qui a fonctionné pour moi.

Supprimez tous les elevationattributs des widgets appBarLayoutet Toolbar(y compris styles.xmlsi vous appliquez un style).

Maintenant, dans l'activité, appliquez le elvationsur votre actionBar:

Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setElevation(3.0f);

Cela devrait fonctionner.


Que faire si je veux l'élévation sur AppBarLayout, car elle peut réduire / développer?
développeur android

1
setElevationprend un paramètre en pixels. Vous devez le convertir de manière appropriée, par exemple(int) (3.0 / Resources.getSystem().getDisplayMetrics().density)
Ely

4

Vous pouvez également le faire fonctionner avec RelativeLayout. Cela réduit un peu l'imbrication de la disposition;)

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include
        android:id="@+id/toolbar"
        layout="@layout/toolbar" />

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/toolbar" />

    <View
        android:layout_width="match_parent"
        android:layout_height="5dp"
        android:layout_below="@id/toolbar"
        android:background="@drawable/toolbar_shadow" />
</RelativeLayout>

3

Tout ce dont vous avez besoin est un android:margin_bottomégal à la android:elevationvaleur. Non AppBarLayout, clipToPaddingetc. requis.

Exemple:

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:layout_marginBottom="4dp"
    android:background="@android:color/white"
    android:elevation="4dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!--Inner layout goes here-->

    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.Toolbar>

rien n'a fonctionné, sauf cela, juste au point et a du sens aussi
DJphy

1

Pour 5.0 +: vous pouvez utiliser AppBarLayout avec Toolbar. AppBarLayout a l'attribution "élévation".

 <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:elevation="4dp"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <include layout="@layout/toolbar" />
    </android.support.design.widget.AppBarLayout>

Qu'en est-il des versions précédentes?
développeur android

1

actionbar_background.xml

    <item>
        <shape>
            <solid android:color="@color/black" />
            <corners android:radius="2dp" />
            <gradient
                android:startColor="@color/black"
                android:centerColor="@color/black"
                android:endColor="@color/white"
                android:angle="270" />
        </shape>
    </item>

    <item android:bottom="3dp" >
        <shape>

            <solid android:color="#ffffff" />
            <corners android:radius="1dp" />
        </shape>
    </item>
</layer-list>

ajouter à l'arrière-plan actionbar_style

<style name="Theme.ActionBar" parent="style/Widget.AppCompat.Light.ActionBar.Solid">
    <item name="background">@drawable/actionbar_background</item>
    <item name="android:elevation">0dp</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:layout_marginBottom">5dp</item>

name = "displayOptions"> useLogo | showHome | showTitle | showCustom

ajouter à Basetheme

<style name="BaseTheme" parent="Theme.AppCompat.Light">
   <item name="android:homeAsUpIndicator">@drawable/home_back</item>
   <item name="actionBarStyle">@style/Theme.ActionBar</item>
</style>

1

La plupart des solutions fonctionnent bien ici. Voudrais montrer une autre alternative similaire:

gradle:

implementation 'androidx.appcompat:appcompat:1.0.0-rc02'
implementation 'com.google.android.material:material:1.0.0-rc02'
implementation 'androidx.core:core-ktx:1.0.0-rc02'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

Votre mise en page peut avoir une vue de la barre d'outils, et une ombre pour elle, ci-dessous, similaire à celle-ci (besoin de modification bien sûr):

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:titleTextAppearance="@style/Base.TextAppearance.Widget.AppCompat.Toolbar.Title"/>

    <include
        layout="@layout/toolbar_action_bar_shadow"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

res / drawable-v21 / toolbar_action_bar_shadow.xml

<androidx.appcompat.widget.AppCompatImageView
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="wrap_content" android:src="@drawable/msl__action_bar_shadow"/>

res / drawable / toolbar_action_bar_shadow.xml

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent" android:layout_height="wrap_content"
    android:foreground="?android:windowContentOverlay" tools:ignore="UnusedAttribute"/>

res / drawable / msl__action_bar_shadow.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <shape
            android:dither="true"
            android:shape="rectangle" >
            <gradient
                android:angle="270"
                android:endColor="#00000000"
                android:startColor="#33000000" />

            <size android:height="10dp" />
        </shape>
    </item>

</layer-list>

styles.xml

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
</resources>

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(toolbar as Toolbar)
    }
}

Exemple complet ici , comme j'ai remarqué que l'EDI a un bogue indiquant que l' foregroundattribut est trop nouveau pour être utilisé ici.



0

La bonne réponse sera d'ajouter
android: backgroundTint = "# ff00ff" à la barre d'outils avec android: background = "@ android: color / white"

Si vous utilisez une autre couleur que le blanc pour l'arrière-plan, cela supprimera l'ombre. Nice one Google!

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.