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);
Mr. Brightside
la source
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

Je suis un dragon grenouille
la source
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

Binoy Babu
la source
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

Muhammad Aamir Ali
la source
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.]

Radley
la source
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>
Islam A. Hassan
la source
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);

Roberto B.
la source
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+

Alex Mazur
la source
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 .

cygery
la source
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.

Irshu
la source
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>
iluu
la source
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>
Rohan Taneja
la source
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>
Eugène Lezov
la source
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>
Samet ÖZTOPRAK
la source
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.

développeur android
la source
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!

user3193413
la source