¿Sin sombra por defecto en la barra de herramientas?

165

Estoy actualizando mi aplicación con la nueva barra de herramientas de la biblioteca de soporte v21. Mi problema es que la barra de herramientas no proyecta ninguna sombra si no configuro el atributo "elevación". ¿Es ese el comportamiento normal o estoy haciendo algo mal?

Mi código es:

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

Y en mi Actividad - Método OnCreate:

    Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
    setSupportActionBar(toolbar);
Mr. Brightside
fuente
¿Estás viendo esto en un dispositivo con Lollipop?
rlay3
3
En un dispositivo que ejecuta Lollipop muestra la sombra debido al atributo de elevación, pero no en KitKat o versiones anteriores. Ese es el comportamiento esperado para el atributo de elevación como dice la documentación, pero esperaba que, por defecto, sin el atributo de elevación, la sombra se proyectaría como lo hace la Barra de acción en cada versión.
MrBrightside
Publiqué una posible solución aquí: stackoverflow.com/a/26759202/553905
Billy
Use las carpetas / values ​​y styles.xml para aplicar el código sombra adecuado según la versión del sistema operativo (consulte a continuación).
radley

Respuestas:

252

Terminé configurando mi propia sombra paralela para la barra de herramientas, pensé que podría ser útil para cualquiera que la buscara:

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

@ color / color_alizarin

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

ingrese la descripción de la imagen aquí

Soy un dragón rana
fuente
3
No olvides ocultar tu vista si el dispositivo que estás ejecutando es> = a Lollipop, si no, terminarás con dos sombras.
mradzinski 01 de
1
Esta es la forma incorrecta de hacerlo porque tendrá que eliminar esa vista para los diseños 5.0. Utilice android: windowContentOverlay o android: foreground en su lugar.
radley
3
Desde Google sobre el diseño del material de la barra Google , debe establecer android:layout_height="4dp"la altura de la sombra, en lugar de 5dp. En realidad, la elevación es igual a la altura de la sombra que estableces FrameLayout.
Anggrayudi H
2
Tengo problemas con esta solución porque inflo el diseño de mis actividades en el diseño del marco en su ejemplo, ¿puede pensar en una forma de que esto funcione?
Zach Sperske
2
Recomiendo usar "android: endColor =" # c7c7c7 "sobre android: endColor =" # 88333333 "
Mohammad Faisal
211

Google lanzó la biblioteca de soporte de diseño hace unas semanas y hay una solución ingeniosa para este problema en esta biblioteca.

Agregue la biblioteca de soporte de diseño como una dependencia en build.gradle:

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

Agregue lo que AppBarLayoutproporciona la biblioteca como envoltorio alrededor de su Toolbardiseño para generar una sombra paralela.

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

Aquí está el resultado:

ingrese la descripción de la imagen aquí

Hay muchos otros trucos con la biblioteca de soporte de diseño.

  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

Como arriba pero con dependencia:

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

y com.google.android.material.appbar.AppBarLayout

Binoy Babu
fuente
26
Establecer el AppBarLayoutcomo un contenedor alrededor del Toolbarno establece ninguna sombra para mí. Tenga en cuenta que no uso un cajón de navegación. ¿Alguna idea de por qué no funciona?
avb
@ avb1994 No puedo decir con certeza, lo he probado sin un cajón de navegación. ¿Puedes publicarlo como una pregunta con el archivo de diseño?
Binoy Babu
vea mi pregunta: stackoverflow.com/questions/31115531/… gracias por su comentario
avb
2
No necesita estas dos líneas compile 'com.android.support:support-v4:22.2.0' compile 'com.android.support:appcompat-v7:22.2.0', porque compila 'com.android.support: diseño: 22.2.0 'depende de ellos
Andrey
8
Tenga en cuenta que esto solo funciona para lollipop y superiores. No funcionará antes de la piruleta ya que debajo solo está usando ViewCompat.setElevation ().
Amirul Zin
25

No puede usar el atributo de elevación antes de API 21 (Android Lollipop). Sin embargo, puede agregar la sombra mediante programación, por ejemplo, utilizando una vista personalizada ubicada debajo de la barra de herramientas.

@ diseño / barra de herramientas

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

en el diseño de tu actividad <include layout="@layout/toolbar" />

ingrese la descripción de la imagen aquí

Muhammad Aamir Ali
fuente
2
¿Puedes arreglar el @layout/toolbarejemplo con el archivo de diseño completo?
Daniel Gomez Rico
1
¿Por qué @ layout / toolbar tiene dos vistas raíz? ¿Puedes dar el ejemplo completo por favor?
RED_
18

Use las carpetas / values para aplicar el estilo de sombra correcto según la versión del sistema operativo.

Para dispositivos con menos de 5.0 , use /values/styles.xml para agregar windowContentOverlay al cuerpo de su actividad:

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

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

Luego agregue su propia sombra personalizada cambiando su Tema para incluir:

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

Puede obtener el recurso sombra de la aplicación IO de Google aquí: https://github.com/google/iosched/blob/master/android/src/main/res/drawable-xxhdpi/bottom_shadow.9.png

Para dispositivos 5.0 y posteriores , use /values-v21/styles.xml para agregar elevación a su barra de herramientas utilizando un estilo de encabezado personalizado:

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

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

Tenga en cuenta que en el segundo caso, tuve que crear un estilo MyViewArea vacío para que windowContentOverlay que no se mostrara .

[Actualización: cambiaron los nombres de los recursos y agregaron Google shadow.]

radley
fuente
¿Puedo saber qué es MyBody y MyHeader? ¿Dónde debo aplicarlos?
Cheok Yan Cheng
Actualicé los nombres: MyHeader ahora es MyToolbar y MyBody es MyViewArea. Puede asignar estilos en diseños xml como este: style = "@ style / MyToolbar".
radley
¿A qué se aplica MyViewArea?
Zach Sperske
Su página / cuerpo / área de visualización.
radley
Creo que android:foregroundsolo funciona en FrameLayout antes de API 23.
androidguy
14

Esto me funcionó muy bien:

<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
fuente
¿Cómo puede funcionar esto si en las tarjetas de vista de tarjeta pre lollipop para dibujar la sombra? Esto es lo que obtengo: i.imgur.com/BIj8env.png esta respuesta funcionó para mí y no sufre los inconvenientes de esta: stackoverflow.com/questions/26575197/…
Aspiring Dev
2
En realidad, es mejor con AppBarLayout como en esta respuesta stackoverflow.com/a/31026359/1451716 Mi respuesta es antigua, antes de que se lanzara AppBarLayout
Islam A. Hassan
¿Es esto legal? Se supone que no debe usarse con la barra Google. ¡DIOS MIO!
user155
12

Si está configurando el ToolBarcomo ActionBar, simplemente llame:

getSupportActionBar().setElevation(YOUR_ELEVATION);

Nota: Esto debe llamarse después setSupportActionBar(toolbar);

Roberto B.
fuente
1
¿Soy yo o el cajón de navegación restablece la elevación de la barra de herramientas? He intentado establecerlo en 0, y funcionó, pero cuando arrastro el cajón de navegación, veo que tiene una sombra de nuevo ...
desarrollador de Android
66
setElevation()aunque solo se define para API-21 +.
Subin Sebastian
@Sebastian La elevación de la barra de acción de soporte también funciona para las API anteriores.
Roberto B.
2
Internamente, eso usa ViewCompat.setElevation()y, por lo tanto, solo funcionará en API 21 en adelante.
botteaap
Utilice android: windowContentOverlay o android: primer plano para bajo API 21.
radley
9

yo añadí

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

en la descripción de la barra de herramientas y funciona para mí. Usando 5.0+

Alex Mazur
fuente
7

Mi problema es que la barra de herramientas no proyecta ninguna sombra si no configuro el atributo "elevación". ¿Es ese el comportamiento normal o estoy haciendo algo mal?

Ese es el comportamiento normal. Consulte también las preguntas frecuentes al final de esta publicación .

cygery
fuente
7

Estaba jugando con esto durante horas, esto es lo que funcionó para mí.

Elimine todos los elevationatributos de los widgets appBarLayouty Toolbar(incluso styles.xmlsi está aplicando algún estilo).

Ahora dentro de la actividad, aplique el elvationen su actionBar:

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

Esto debería funcionar.

Irshu
fuente
¿Qué sucede si quiero la elevación en AppBarLayout, ya que puede colapsar / expandirse?
Desarrollador de Android
1
setElevationtoma un parámetro como píxeles. Tienes que convertirlo adecuadamente, por ejemplo(int) (3.0 / Resources.getSystem().getDisplayMetrics().density)
Ely
4

También puedes hacer que funcione RelativeLayout. Esto reduce un poco la anidación del diseño;)

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

Todo lo que necesitas es un valor android:margin_bottomigual android:elevation. No AppBarLayout, clipToPaddingetc. requerido.

Ejemplo:

<?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
fuente
nada funcionó, excepto esto, justo en el punto y tiene sentido también
DJphy
1

Para 5.0+: puede usar AppBarLayout con Toolbar. AppBarLayout tiene un atributo de "elevación".

 <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>
Eugene Lezov
fuente
¿Qué pasa con las versiones anteriores?
Desarrollador de 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>

agregar al fondo 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>

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

agregar 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>
Samet ÖZTOPRAK
fuente
1

La mayoría de las soluciones funcionan bien aquí. Me gustaría mostrar otra alternativa similar:

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'

Su diseño puede tener una Vista de barra de herramientas y una sombra para ello, a continuación, similar a esto (necesita modificación, por supuesto):

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

Muestra completa aquí , como he notado, el IDE tiene el error de decir que el foregroundatributo es demasiado nuevo para usarlo aquí.

desarrollador de Android
fuente
0

La respuesta correcta será agregar
android: backgroundTint = "# ff00ff" a la barra de herramientas con android: background = "@ android: color / white"

Si usa otro color, entonces blanco para el fondo, eliminará la sombra. Nice one Google!

usuario3193413
fuente