Standardmäßig kein Schatten in der Symbolleiste?


164

Ich aktualisiere meine App mit der neuen Symbolleiste aus der Support-Bibliothek v21. Mein Problem ist, dass die Symbolleiste keinen Schatten wirft, wenn ich das Attribut "Höhe" nicht festlege. Ist das das normale Verhalten oder mache ich etwas falsch?

Mein Code lautet:

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

Und in meiner Aktivität - OnCreate-Methode:

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

Sehen Sie dies auf einem Gerät, auf dem Lollipop ausgeführt wird?
Rlay3

3
Auf einem Gerät, auf dem Lollipop ausgeführt wird, wird der Schatten aufgrund des Höhenattributs angezeigt, jedoch nicht auf KitKat oder älteren Versionen. Das ist das erwartete Verhalten für das Höhenattribut, wie in der Dokumentation angegeben, aber ich hatte erwartet, dass der Schatten standardmäßig ohne das Höhenattribut so geworfen wird, wie es die Aktionsleiste bei jeder Version tut.
MrBrightside

Ich habe hier eine mögliche Lösung veröffentlicht: stackoverflow.com/a/26759202/553905
Billy

Verwenden Sie die Ordner / values ​​und die Datei styles.xml, um den richtigen Schattencode basierend auf der Betriebssystemversion anzuwenden (siehe unten).
Radley

Antworten:


252

Am Ende habe ich meinen eigenen Schlagschatten für die Symbolleiste festgelegt und dachte, er könnte für jeden hilfreich sein, der danach sucht:

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

Geben Sie hier die Bildbeschreibung ein


3
Vergessen Sie nicht, Ihre Ansicht auszublenden, wenn das Gerät, das Sie ausführen,> = für Lollipop ist. Andernfalls erhalten Sie zwei Schatten.
mradzinski

1
Dies ist der falsche Weg, da Sie diese Ansicht für 5.0-Layouts entfernen müssen. Verwenden Sie stattdessen android: windowContentOverlay oder android: foreground.
Radley

3
Bei Google zum Entwerfen des Symbolleisten-Materialdesigns sollten Sie android:layout_height="4dp"stattdessen die Höhe des Schattens festlegen 5dp. Tatsächlich entspricht die Höhe der Schattenhöhe, auf die Sie eingestellt haben FrameLayout.
Anggrayudi H

2
Ich habe Probleme mit dieser Lösung, weil ich mein Aktivitätslayout in das Rahmenlayout in Ihrem Beispiel aufblase. Können Sie sich eine Möglichkeit vorstellen, wie dies funktioniert?
Zach Sperske

2
Empfehlung mit "android: endColor =" # c7c7c7 "über android: endColor =" # 88333333 "
Mohammad Faisal

211

Google hat die Design Support-Bibliothek vor einigen Wochen veröffentlicht. In dieser Bibliothek gibt es eine raffinierte Lösung für dieses Problem.

Fügen Sie die Design Support-Bibliothek als Abhängigkeit hinzu in build.gradle:

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

Fügen Sie AppBarLayoutvon der Bibliothek bereitgestelltes Wrapper um Ihr ToolbarLayout hinzu, um einen Schlagschatten zu erzeugen.

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

Hier ist das Ergebnis:

Geben Sie hier die Bildbeschreibung ein

Es gibt viele andere Tricks mit der Design-Support-Bibliothek.

  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

Wie oben, jedoch mit Abhängigkeit:

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

und com.google.android.material.appbar.AppBarLayout


26
Das Setzen AppBarLayoutals Wrapper um das Toolbarsetzt für mich keinen Schatten. Beachten Sie, dass ich keine Navigationsschublade verwende. Irgendwelche Ideen, warum es nicht funktioniert?
Avb

@ avb1994 Kann nicht sicher sagen, ich habe es ohne Navi-Schublade getestet. Können Sie es als Frage mit der Layoutdatei posten?
Binoy Babu

siehe meine Frage: stackoverflow.com/questions/31115531/… danke für deinen Kommentar
avb

2
Sie brauchen diese zwei Zeilen nicht, um 'com.android.support:support-v4:22.2.0' zu kompilieren 'com.android.support:appcompat-v7:22.2.0' zu kompilieren, weil 'com.android.support kompiliert: Design: 22.2.0 'hängt von ihnen ab
Andrey

8
Beachten Sie, dass dies nur für Lutscher und höher funktioniert. Vor dem Lutschern funktioniert es nicht, da darunter nur ViewCompat.setElevation () verwendet wird.
Amirul Zin

25

Sie können das Höhenattribut nicht vor API 21 (Android Lollipop) verwenden. Sie können den Schatten jedoch programmgesteuert hinzufügen, z. B. mithilfe einer benutzerdefinierten Ansicht unterhalb der Symbolleiste.

@ Layout / Symbolleiste

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

in Ihrem Aktivitätslayout <include layout="@layout/toolbar" />

Geben Sie hier die Bildbeschreibung ein


2
Können Sie ein @layout/toolbarBeispiel mit einer vollständigen Layoutdatei reparieren ?
Daniel Gomez Rico

1
Warum hat @ layout / toolbar zwei Stammansichten? Können Sie bitte das vollständige Beispiel angeben?
RED_

18

Verwenden Sie die Ordner / values , um den richtigen Schattenstil basierend auf der Betriebssystemversion anzuwenden.

Verwenden Sie für Geräte unter 5.0 /values/styles.xml , um windowContentOverlay zum Hauptteil Ihrer Aktivität hinzuzufügen :

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

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

Fügen Sie dann Ihren eigenen Schatten hinzu, indem Sie Ihr Thema so ändern, dass es Folgendes enthält:

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

Sie können die Schattenressource der IO-App von Google hier herunterladen : https://github.com/google/iosched/blob/master/android/src/main/res/drawable-xxhdpi/bottom_shadow.9.png

Verwenden Sie für Geräte der Version 5.0 und höher /values-v21/styles.xml , um Ihrer Symbolleiste mithilfe eines benutzerdefinierten Kopfzeilenstils eine Höhe hinzuzufügen :

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

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

Beachten Sie, dass ich im zweiten Fall einen leeren MyViewArea- Stil erstellen musste, damit windowContentOverlay angezeigt wird nicht wird.

[Update: Ressourcennamen geändert und Google Shadow hinzugefügt.]


Darf ich wissen, was MyBody und MyHeader sind? Wo soll ich sie anwenden?
Cheok Yan Cheng

Ich habe die Namen aktualisiert: MyHeader ist jetzt MyToolbar und MyBody ist MyViewArea. Sie können Stile in XML-Layouts wie folgt zuweisen: style = "@ style / MyToolbar".
Radley

Worauf wird MyViewArea angewendet?
Zach Sperske

Ihr Seiten- / Körper- / Ansichtsbereich.
Radley

Ich denke android:foreground, funktioniert nur auf FrameLayout vor API 23.
androidguy

14

Das hat bei mir sehr gut funktioniert:

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

Wie kann dies funktionieren, wenn sich auf Pre-Lollipop-Kartenansicht-Pads selbst der Schatten zeichnet? Folgendes bekomme ich: i.imgur.com/BIj8env.png Diese Antwort hat bei mir funktioniert und leidet nicht unter den Nachteilen dieser: stackoverflow.com/questions/26575197/…
Aspiring Dev

2
Eigentlich sind Sie mit dem AppBarLayout besser dran als in dieser Antwort stackoverflow.com/a/31026359/1451716 Meine Antwort ist alt, bevor das AppBarLayout veröffentlicht wurde
Islam A. Hassan

Ist das überhaupt legal? Es sollte nicht mit der Symbolleiste verwendet werden. OH MEIN GOTT!
user155

12

Wenn Sie das ToolBarals einstellen, ActionBarrufen Sie einfach an:

getSupportActionBar().setElevation(YOUR_ELEVATION);

Hinweis: Dies muss nach aufgerufen werden setSupportActionBar(toolbar);


1
Bin ich es nur, oder setzt die Navigationsleiste die Höhe der Symbolleiste zurück? Ich habe versucht, es auf 0 zu setzen, und es hat funktioniert, aber wenn ich dann die Navigationsschublade ziehe, sehe ich, dass es wieder einen Schatten hat ...
Android-Entwickler

6
setElevation()ist jedoch nur für API-21 + definiert.
Subin Sebastian

@Sebastian Die Erhöhung der Unterstützungsaktionsleiste funktioniert auch für frühere APIs.
Roberto B.

2
Intern verwendet das ViewCompat.setElevation()und funktioniert daher nur mit API 21 und höher.
Botteaap

Verwenden Sie android: windowContentOverlay oder android: Vordergrund für unter API 21.
Radley

9

Ich fügte hinzu

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

in der Symbolleistenbeschreibung und es funktioniert für mich. Verwenden von 5.0+


7

Mein Problem ist, dass die Symbolleiste keinen Schatten wirft, wenn ich das Attribut "Höhe" nicht festlege. Ist das das normale Verhalten oder mache ich etwas falsch?

Das ist das normale Verhalten. Siehe auch die FAQ am Ende dieses Beitrags .


7

Ich habe stundenlang damit gespielt, hier ist, was für mich funktioniert hat.

Entfernen Sie alle elevationAttribute aus den Widgets appBarLayoutund Toolbar(auch styles.xmlwenn Sie ein Styling anwenden).

Wenden Sie nun innerhalb der Aktivität Folgendes elvationan actionBar:

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

Das sollte funktionieren.


Was ist, wenn ich die Höhe im AppBarLayout haben möchte, da sie reduziert / erweitert werden kann?
Android-Entwickler

1
setElevationNimmt einen Parameter als Pixel. Sie müssen es entsprechend konvertieren, zB(int) (3.0 / Resources.getSystem().getDisplayMetrics().density)
Ely

4

Sie können es auch zum Laufen bringen RelativeLayout. Dies reduziert die Verschachtelung des Layouts ein wenig;)

<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

Alles was Sie brauchen ist android:margin_bottomgleich dem android:elevationWert. Nein AppBarLayout, clipToPaddingusw. erforderlich.

Beispiel:

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

nichts hat funktioniert, außer dies, genau richtig und auch sinnvoll
DJphy

1

Für 5.0 +: Sie können AppBarLayout mit Symbolleiste verwenden. AppBarLayout hat die Zuordnung "Höhe".

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

Was ist mit früheren Versionen?
Android-Entwickler

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>

zum actionbar_style Hintergrund hinzufügen

<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

zu Basetheme hinzufügen

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

1

Die meisten Lösungen funktionieren hier einwandfrei. Möchte eine andere, ähnliche Alternative zeigen:

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'

Ihr Layout kann eine Symbolleistenansicht und einen Schatten dafür haben, ähnlich wie dieser (muss natürlich geändert werden):

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

Vollständiges Beispiel hier , da ich festgestellt habe, dass die IDE den Fehler hat, dass das foregroundAttribut zu neu ist, um hier verwendet zu werden.


0

Ich hatte ein ähnliches Problem mit dem Schatten. Der Schatten wird in meinem Fall vom direkten übergeordneten Element von AppBarLayout gezeichnet. Wenn die Höhe des übergeordneten Elements mit der von AppBarLayout übereinstimmt, kann der Schatten nicht gezeichnet werden. Das Überprüfen der Größe des übergeordneten Layouts und möglicherweise des Layout-Remakes kann das Problem lösen. https://www.reddit.com/r/androiddev/comments/6xddb0/having_a_toolbar_as_a_fragment_the_shadow/


0

Die richtige Antwort ist,
android: backgroundTint = "# ff00ff" zur Symbolleiste mit android: background = "@ android: color / white" hinzuzufügen.

Wenn Sie eine andere Farbe als Weiß als Hintergrund verwenden, wird der Schatten entfernt. Netter Google!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.