Nessuna ombra di default su Toolbar?


165

Sto aggiornando la mia app con la nuova barra degli strumenti dalla libreria di supporto v21. Il mio problema è che la barra degli strumenti non getta alcuna ombra se non imposto l'attributo "elevazione". È un comportamento normale o sto facendo qualcosa di sbagliato?

Il mio codice è:

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

E nella mia attività - Metodo OnCreate:

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

Lo vedi su un dispositivo con Lollipop?
rlay3,

3
Su un dispositivo che esegue Lollipop mostra l'ombra a causa dell'attributo elevazione ma non su KitKat o versioni precedenti. Questo è il comportamento previsto per l'attributo elevazione come dice la documentazione, ma mi aspettavo che, per impostazione predefinita senza l'attributo elevazione, l'ombra avrebbe lanciato come se fosse la barra delle azioni su ogni versione.
MrBrightside,

Ho pubblicato una possibile soluzione qui: stackoverflow.com/a/26759202/553905
Billy

Utilizzare / valori cartelle e styles.xml per applicare il codice ombra corretto in base alla versione del sistema operativo (vedere di seguito).
radley,

Risposte:


252

Ho finito per impostare la mia ombra esterna per la barra degli strumenti, ho pensato che potesse essere utile per chiunque lo cercasse:

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

@ Colore / color_alizarin

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

inserisci qui la descrizione dell'immagine


3
Non dimenticare di nascondere la vista se il dispositivo che stai utilizzando è> = per Lollipop, altrimenti finirai con due ombre.
mradzinski,

1
Questo è il modo sbagliato per farlo perché dovrai rimuovere quella vista per i layout 5.0. Usa invece android: windowContentOverlay o android: foreground.
Radley,

3
Da Google sulla progettazione del design del materiale della barra degli strumenti , è necessario impostare android:layout_height="4dp"l'altezza dell'ombra anziché 5dp. In realtà, l'elevazione è uguale all'altezza dell'ombra impostata FrameLayout.
Anggrayudi H,

2
Sto riscontrando problemi con questa soluzione perché gonfio il layout delle mie attività nel layout del frame nel tuo esempio, riesci a pensare a un modo per farlo funzionare?
Zach Sperske,

2
Raccomandando di usare "android: endColor =" # c7c7c7 "su android: endColor =" # 88333333 "
Mohammad Faisal

211

Google ha rilasciato la libreria di supporto alla progettazione qualche settimana fa e in questa libreria è presente una soluzione elegante per questo problema.

Aggiungi la libreria del supporto di progettazione come dipendenza in build.gradle:

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

Aggiungi AppBarLayoutfornito dalla libreria come wrapper attorno al Toolbarlayout per generare un'ombra esterna.

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

Ecco il risultato:

inserisci qui la descrizione dell'immagine

Ci sono molti altri trucchi con la libreria di supporto alla progettazione.

  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

Come sopra ma con dipendenza:

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

e com.google.android.material.appbar.AppBarLayout


26
Impostare AppBarLayoutcome un wrapper attorno a Toolbarnon crea alcuna ombra per me. Nota che non utilizzo un cassetto di navigazione. Qualche idea sul perché non funziona?
aprile

@ avb1994 Non posso dire con certezza, l'ho provato senza un cassetto di navigazione. Puoi pubblicarlo come una domanda con il file di layout?
Binoy Babu,

vedi la mia domanda: stackoverflow.com/questions/31115531/… grazie per il tuo commento
avb

2
Non hai bisogno di queste due righe compilare 'com.android.support:support-v4:22.2.0' compilare 'com.android.support:appcompat-v7:22.2.0', perché compilare 'com.android.support: design: 22.2.0 'dipende da loro
Andrey

8
Nota che funziona solo con lecca-lecca e superiori. Non funzionerà pre-lecca-lecca poiché sotto sta solo usando ViewCompat.setElevation ().
Amirul Zin,

25

Non è possibile utilizzare l'attributo elevazione prima dell'API 21 (Android Lollipop). È tuttavia possibile aggiungere l'ombra a livello di codice, ad esempio utilizzando una vista personalizzata posizionata sotto la barra degli strumenti.

@ Layout / barra degli strumenti

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

nel layout dell'attività <include layout="@layout/toolbar" />

inserisci qui la descrizione dell'immagine


2
Puoi risolvere l' @layout/toolbaresempio con il file di layout completo?
Daniel Gomez Rico,

1
Perché @ layout / toolbar ha due viste root? Potete fornire l'esempio completo per favore?
RED_

18

Utilizzare le cartelle / valori per applicare lo stile ombra corretto in base alla versione del sistema operativo.

Per meno di 5.0 dispositivi , uso /values/styles.xml per aggiungere windowContentOverlay al corpo della vostra attività:

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

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

Quindi aggiungi la tua ombra personalizzata modificando il tema per includere:

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

Puoi prendere la risorsa shadow dell'app IO di Google qui: https://github.com/google/iosched/blob/master/android/src/main/res/drawable-xxhdpi/bottom_shadow.9.png

Per i dispositivi 5.0 e versioni successive , utilizzare /values-v21/styles.xml per aggiungere l' elevazione alla barra degli strumenti utilizzando uno stile di intestazione personalizzato:

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

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

Si noti che nel secondo caso, ho dovuto creare un vuoto MyViewArea stile in modo che il windowContentOverlay non avrebbe mostrato troppo.

[Aggiornamento: ha cambiato i nomi delle risorse e aggiunto Google Shadow.]


Posso sapere cosa sono MyBody e MyHeader? Dove dovrei applicarli?
Cheok Yan Cheng,

Ho aggiornato i nomi: MyHeader ora è MyToolbar e MyBody è MyViewArea. È possibile assegnare stili in layout XML come questo: style = "@ style / MyToolbar".
Radley,

A cosa si applica MyViewArea?
Zach Sperske,

La tua pagina / corpo / area di visualizzazione.
Radley,

Penso che android:foregroundfunzioni solo su FrameLayout prima dell'API 23.
androidguy

14

Questo ha funzionato molto bene per me:

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

Come può funzionare se sui pad cardview pre-lollipop si disegna per disegnare l'ombra? Questo è quello che ottengo: i.imgur.com/BIj8env.png questa risposta ha funzionato per me e non presenta gli svantaggi di questo: stackoverflow.com/questions/26575197/…
Aspiring Dev

2
In realtà, stai meglio con AppBarLayout come in questa risposta stackoverflow.com/a/31026359/1451716 La mia risposta è vecchia, prima che l'appBarLayout fosse rilasciato
Islam A. Hassan

È legale? Non dovrebbe essere usato con Toolbar. OH MIO DIO!
user155

12

Se si sta impostando il ToolBarcome ActionBarallora basta chiamare:

getSupportActionBar().setElevation(YOUR_ELEVATION);

Nota: questo deve essere chiamato dopo setSupportActionBar(toolbar);


1
Sono solo io o il cassetto di navigazione ripristina l'elevazione della barra degli strumenti? Ho provato a impostarlo su 0, e ha funzionato, ma quando trascino il cassetto di navigazione, vedo che ha di nuovo un'ombra ...
sviluppatore Android

6
setElevation()è definito solo per API-21 + però.
Sottomissione Sebastian

@Sebastian L'elevazione della barra delle azioni di supporto funziona anche per le API precedenti.
Roberto B.

2
Internamente che utilizza ViewCompat.setElevation()e quindi funzionerà solo su API 21 e versioni successive.
botteaap,

Usa android: windowContentOverlay o android: foreground per under API 21.
radley

9

Ho aggiunto

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

nella descrizione della barra degli strumenti e funziona per me. Usando 5.0+


7

Il mio problema è che la barra degli strumenti non getta alcuna ombra se non imposto l'attributo "elevazione". È un comportamento normale o sto facendo qualcosa di sbagliato?

Questo è il comportamento normale. Vedi anche le FAQ alla fine di questo post .


7

Stavo giocando con questo per ore, ecco cosa ha funzionato per me.

Rimuovi tutti gli elevationattributi dai widget appBarLayoute Toolbar(anche styles.xmlse stai applicando uno stile).

Ora all'interno dell'attività, applica il elvationtuo actionBar:

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

Questo dovrebbe funzionare.


Cosa succede se desidero l'elevazione su AppBarLayout, in quanto può comprimere / espandere?
sviluppatore Android il

1
setElevationaccetta un parametro come pixel. Devi convertirlo in modo appropriato, ad es.(int) (3.0 / Resources.getSystem().getDisplayMetrics().density)
Ely

4

Puoi anche farlo funzionare con RelativeLayout. Questo riduce un po 'l'annidamento del layout;)

<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

Tutto ciò che serve è android:margin_bottomuguale al android:elevationvalore. No AppBarLayout, clipToPaddingecc. Richiesto.

Esempio:

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

niente ha funzionato, tranne questo, giusto e anche sensato
DJphy

1

Per 5.0+: puoi usare AppBarLayout con Toolbar. AppBarLayout ha attributo "elevazione".

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

Che dire delle versioni precedenti?
sviluppatore Android il

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>

aggiungi allo sfondo 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

aggiungi a 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 maggior parte delle soluzioni funziona bene qui. Vorrei mostrare un'altra alternativa simile:

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'

Il layout può avere una vista della barra degli strumenti e un'ombra per essa, di seguito, simile a questa (è necessario modificarla ovviamente):

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

Esempio completo qui , come ho notato l'IDE ha un bug nel dire che l' foregroundattributo è troppo nuovo per essere usato qui.



0

La risposta corretta sarà aggiungere
android: backgroundTint = "# ff00ff" alla barra degli strumenti con android: background = "@ android: color / white"

Se usi un altro colore, allora il bianco per lo sfondo rimuoverà l'ombra. Bel Google!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.