Domyślnie brak cienia na pasku narzędzi Toolbar?

165

Aktualizuję aplikację za pomocą nowego paska narzędzi Toolbar z biblioteki pomocy technicznej w wersji 21. Mój problem polega na tym, że pasek narzędzi nie rzuca żadnego cienia, jeśli nie ustawię atrybutu „wysokość”. Czy to normalne zachowanie, czy robię coś złego?

Mój kod to:

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

A w mojej aktywności - metoda OnCreate:

    Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
    setSupportActionBar(toolbar);
Pan Brightside
źródło
Czy widzisz to na urządzeniu z Lollipopem?
rlay3
3
Na urządzeniu z systemem Lollipop wyświetla cień ze względu na atrybut elewacji, ale nie w KitKat lub starszych wersjach. Jest to oczekiwane zachowanie atrybutu elewacji, jak mówi dokumentacja, ale spodziewałem się, że domyślnie bez atrybutu elewacji cień będzie rzucany tak, jak robi to pasek akcji w każdej wersji.
MrBrightside
Tutaj zamieściłem możliwe rozwiązanie: stackoverflow.com/a/26759202/553905
Billy
Użyj folderów / values ​​i styles.xml, aby zastosować właściwy kod shadow w oparciu o wersję systemu operacyjnego (patrz poniżej).
radley

Odpowiedzi:

252

Skończyło się na ustawieniu własnego cienia dla paska narzędzi, pomyślałem, że może to być pomocne dla każdego, kto go szuka:

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

wprowadź opis obrazu tutaj

Jestem żabim smokiem
źródło
3
Nie zapomnij ukryć widoku, jeśli urządzenie, które używasz, jest> = do Lollipopa, jeśli nie, skończysz z dwoma cieniami.
mradzinski
1
To jest zły sposób, ponieważ będziesz musiał usunąć ten widok dla układów 5.0. Zamiast tego użyj android: windowContentOverlay lub android: foreground.
radley
3
Od Google, jeśli chodzi o projektowanie materiału paska narzędzi Toolbar , należy ustawić android:layout_height="4dp"wysokość cienia zamiast 5dp. W rzeczywistości wysokość jest taka sama, jak wysokość ustawionego cienia FrameLayout.
Anggrayudi H
2
Mam problem z tym rozwiązaniem, ponieważ dodałem układ moich działań do układu ramek w twoim przykładzie. Czy możesz wymyślić sposób, aby to zadziałało?
Zach Sperske,
2
Rekomendowanie korzystania z „android: endColor =" # c7c7c7 "na android: endColor =" # 88333333 "
Mohammad Faisal
211

Firma Google udostępniła bibliotekę Design Support kilka tygodni temu iw tej bibliotece jest sprytne rozwiązanie tego problemu.

Dodaj bibliotekę Design Support jako zależność w build.gradle:

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

Dodaj AppBarLayoutdostarczone przez bibliotekę jako opakowanie wokół Toolbarukładu, aby wygenerować cień.

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

Oto wynik:

wprowadź opis obrazu tutaj

Istnieje wiele innych sztuczek związanych z biblioteką wsparcia projektowania.

  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

Jak wyżej, ale z zależnością:

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

i com.google.android.material.appbar.AppBarLayout

Binoy Babu
źródło
26
Ustawienie go AppBarLayoutjako otuliny Toolbarnie stanowi dla mnie żadnego cienia. Pamiętaj, że nie używam szuflady nawigacji. Jakieś pomysły, dlaczego to nie działa?
avb
@ avb1994 Nie mogę powiedzieć na pewno, testowałem to bez szuflady nawigacji. Czy możesz opublikować to jako pytanie z plikiem układu?
Binoy Babu
zobacz moje pytanie: stackoverflow.com/questions/31115531/… dzięki za komentarz
avb
2
Nie potrzebujesz tych dwóch wierszy do kompilacji „com.android.support:support-v4:22.2.0” compile ”com.android.support:appcompat-v7:22.2.0”, ponieważ kompiluj „com.android.support: projekt: 22.2.0 'zależy od nich
Andrey
8
Zwróć uwagę, że działa to tylko w przypadku Lollipopa i nowszych wersji. Nie będzie działać przed Lollipopem, ponieważ pod spodem używa tylko ViewCompat.setElevation ().
Amirul Zin
25

Nie możesz użyć atrybutu Elevation przed API 21 (Android Lollipop). Możesz jednak dodać cień programowo, na przykład używając widoku niestandardowego umieszczonego poniżej paska narzędzi.

@ układ / pasek narzędzi

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

w układzie aktywności <include layout="@layout/toolbar" />

wprowadź opis obrazu tutaj

Muhammad Aamir Ali
źródło
2
Czy możesz naprawić @layout/toolbarprzykład z pełnym plikiem układu?
Daniel Gomez Rico
1
Dlaczego @ layout / toolbar ma dwa widoki główne? Czy możesz podać pełny przykład?
RED_
18

Użyj / wartości folderów aby zastosować właściwy styl cienia na podstawie wersji systemu operacyjnego.

W przypadku urządzeń poniżej 5.0 użyj /values/styles.xml, aby dodać windowContentOverlay do treści swojej aktywności:

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

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

Następnie dodaj własny niestandardowy cień, zmieniając motyw, aby uwzględnić:

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

Możesz pobrać zasób cienia aplikacji Google IO tutaj: https://github.com/google/iosched/blob/master/android/src/main/res/drawable-xxhdpi/bottom_shadow.9.png

W przypadku urządzeń 5.0 i nowszych użyj /values-v21/styles.xml, aby dodać podniesienie do paska narzędzi za pomocą niestandardowego stylu nagłówka:

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

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

Zwróć uwagę, że w drugim przypadku musiałem utworzyć pusty MyViewArea styl , aby plik windowContentOverlay się nie .

[Aktualizacja: zmienione nazwy zasobów i dodane Google shadow.]

radley
źródło
Czy mogę wiedzieć, co to jest MyBody i MyHeader? Gdzie mam je zastosować?
Cheok Yan Cheng
Zaktualizowałem nazwy: MyHeader to teraz MyToolbar, a MyBody to MyViewArea. Możesz przypisywać style w układach xml w następujący sposób: style = "@ style / MyToolbar".
radley
Do czego ma zastosowanie MyViewArea?
Zach Sperske
Twoja strona / treść / obszar widoku.
radley,
Myślę, że android:foregrounddziała tylko na FrameLayout przed API 23.
androidguy
14

To zadziałało dla mnie bardzo dobrze:

<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
źródło
Jak to może działać, jeśli na kartach typu pre Lollipop, aby narysować cień? Oto, co otrzymałem: i.imgur.com/BIj8env.png ta odpowiedź zadziałała dla mnie i nie ma jej wad: stackoverflow.com/questions/26575197/…
Aspiring Dev
2
Właściwie lepiej jest z AppBarLayout, jak w tej odpowiedzi stackoverflow.com/a/31026359/1451716 Moja odpowiedź jest stara, zanim AppBarLayout został wydany
Islam A. Hassan
Czy to w ogóle legalne? Nie powinno być używane z paskiem narzędzi. O MÓJ BOŻE!
user155
12

Jeśli ustawiasz ToolBaras ActionBarto po prostu zadzwoń:

getSupportActionBar().setElevation(YOUR_ELEVATION);

Uwaga: należy to wywołać później setSupportActionBar(toolbar);

Roberto B.
źródło
1
Czy to tylko ja, czy szuflada nawigacji zresetowała wysokość paska narzędzi? Próbowałem ustawić to na 0 i zadziałało, ale kiedy przeciągam szufladę nawigacji, widzę, że znów ma cień ...
programista Androida
6
setElevation()jest jednak zdefiniowany tylko dla API-21 +.
Subin Sebastian,
@Sebastian Obsługa podniesienia paska akcji działa również dla poprzednich interfejsów API.
Roberto B.
2
Wewnętrznie to używa ViewCompat.setElevation()i dlatego będzie działać tylko na API 21 i nowszych.
botteaap
Użyj android: windowContentOverlay lub android: foreground dla API 21
radley
9

dodałem

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

w opisie paska narzędzi i to działa dla mnie. Używam 5.0+

Alex Mazur
źródło
7

Mój problem polega na tym, że pasek narzędzi nie rzuca żadnego cienia, jeśli nie ustawię atrybutu „wysokość”. Czy to normalne zachowanie, czy robię coś złego?

To normalne zachowanie. Zobacz także FAQ na końcu tego postu .

cygery
źródło
7

Bawiłem się tym godzinami, oto co mi zadziałało.

Usuń wszystkie elevationatrybuty z widżetów appBarLayouti Toolbar(w tymstyles.xml przypadku stosowania stylów).

Teraz aktywność wewnętrzna, zastosuj elvationna actionBar:

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

To powinno działać.

Irshu
źródło
Co zrobić, jeśli chcę, aby elewacja na AppBarLayout, ponieważ może zwinąć / rozwinąć?
programista Androida
1
setElevationprzyjmuje parametr w pikselach. Trzeba to odpowiednio przekonwertować, np.(int) (3.0 / Resources.getSystem().getDisplayMetrics().density)
Ely
4

Możesz także sprawić, by to działało RelativeLayout. Zmniejsza to trochę zagnieżdżanie układu;)

<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
źródło
3

Wszystko, czego potrzebujesz, to android:margin_bottomrówna android:elevationwartości. Nie AppBarLayout, clipToPaddingitp. Wymagane.

Przykład:

<?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
źródło
nic nie działało, z wyjątkiem tego, dokładnie na miejscu i też ma sens
DJphy
1

Wersja 5.0 +: możesz używać AppBarLayout z paskiem narzędzi. AppBarLayout ma atrybut „podniesienie uprawnień”.

 <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
źródło
A co z poprzednimi wersjami?
programista Androida
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>

dodaj do tła 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

dodaj do 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
źródło
1

Większość rozwiązań działa tutaj dobrze. Chciałbym pokazać inną, podobną alternatywę:

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'

Możesz mieć widok paska narzędzi i cień poniżej, podobny do tego (oczywiście wymaga modyfikacji):

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

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

Pełna próbka tutaj , jak zauważyłem, IDE ma błąd polegający na tym, że foregroundatrybut jest zbyt nowy, aby go tutaj użyć.

programista Androida
źródło
0

Poprawną odpowiedzią będzie dodanie
android: backgroundTint = "# ff00ff" do paska narzędzi za pomocą android: background = "@ android: color / white"

Jeśli użyjesz innego koloru niż biały jako tło, usunie cień. Niezły Google!

user3193413
źródło