Нет тени по умолчанию на панели инструментов?


165

Я обновляю свое приложение новой панелью инструментов из библиотеки поддержки v21. Моя проблема заключается в том, что панель инструментов не отбрасывает тени, если я не установил атрибут «Высота». Это нормальное поведение или я что-то не так делаю?

Мой код:

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

И в моей Деятельности - метод OnCreate:

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

Вы видите это на устройстве под управлением Lollipop?
— rlay3

3
На устройстве под управлением Lollipop отображается тень из-за атрибута повышения прав, но не в KitKat или более старых версиях. Это ожидаемое поведение для атрибута повышения, как сказано в документации, но я ожидал, что по умолчанию без атрибута повышения тень будет отбрасываться, как это делает Панель действий в каждой версии.
— MrBrightside

Я разместил возможное решение здесь: stackoverflow.com/a/26759202/553905
— Билли

Используйте / values ​​папки и styles.xml, чтобы применить правильный теневой код в зависимости от версии ОС (см. Ниже).
— Рэдли

Ответы:


252

В итоге я установил собственную тень для панели инструментов, и подумал, что это может пригодиться всем, кто ее ищет:

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

@ Вытяжка / 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_alizarin

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

введите описание изображения здесь


3
Не забудьте спрятать свой взгляд, если устройство, на котором вы работаете,>> = Lollipop, в противном случае вы получите две тени.
— Мрадзински

1
Это неправильный способ, потому что вам придется удалить это представление для макетов 5.0. Вместо этого используйте android: windowContentOverlay или android: foreground.
— Рэдли

3
От Google о разработке дизайна материала панели инструментов , вы должны установить android:layout_height="4dp"высоту тени, а не 5dp. Фактически, высота равна высоте тени, которую вы установили FrameLayout.
— Anggrayudi H

2
У меня проблемы с этим решением, потому что я надуваю макет своей деятельности в макете фрейма в вашем примере. Можете ли вы придумать, как это работает?
— Зак Сперске

2
Рекомендую использовать "android: endColor =" # c7c7c7 "поверх android: endColor =" # 88333333 "
— Мохаммед Фейсал

211

Google выпустил библиотеку поддержки проектирования несколько недель назад, и в этой библиотеке есть отличное решение этой проблемы.

Добавьте библиотеку поддержки проектирования в качестве зависимости в build.gradle:

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

Добавьте AppBarLayoutпредоставленный библиотекой обертку вокруг Toolbarмакета, чтобы создать тень.

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

Вот результат:

введите описание изображения здесь

Есть много других хитростей с библиотекой поддержки дизайна.

  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

Как указано выше, но с зависимостью:

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

и com.google.android.material.appbar.AppBarLayout


26
Установка в AppBarLayoutкачестве обертки вокруг Toolbarне создает никакой тени для меня. Обратите внимание, что я не использую навигационный ящик. Есть идеи, почему это не работает?
— AVB

@ avb1994 Не могу сказать точно, я проверил это без навигационного ящика. Можете ли вы опубликовать это как вопрос с файлом макета?
— Биной ​​Бабу

см. мой вопрос: stackoverflow.com/questions/31115531/… спасибо за ваш комментарий
— avb

2
Вам не нужны эти две строки: compile 'com.android.support:support-v4:22.2.0' compile 'com.android.support:appcompat-v7:22.2.0', потому что compile 'com.android.support: дизайн: 22.2.0 'зависит от них
— Андрей

8
Обратите внимание, что это работает только для леденцов и выше. Он не будет работать до леденца, поскольку под ним просто используется ViewCompat.setElevation ().
— Амирул Зин

25

Вы не можете использовать атрибут повышения до API 21 (Android Lollipop). Однако вы можете добавить тень программно, например, используя пользовательский вид, расположенный под панелью инструментов.

@ Макет / панель

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

@ Вытяжка / 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>

в макете вашей деятельности <include layout="@layout/toolbar" />

введите описание изображения здесь


2
Можете ли вы исправить @layout/toolbarпример с полным файлом макета?
— Даниэль Гомес Рико

1
Почему @ layout / toolbar имеет два корневых представления? Можете ли вы привести полный пример, пожалуйста?
— RED_

18

Используйте папки / values для применения правильного стиля тени в зависимости от версии ОС.

Для устройств до версии 5.0 используйте /values/styles.xml, чтобы добавить windowContentOverlay к основной части своей деятельности:

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

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

Затем добавьте свою собственную тень, изменив тему:

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

Вы можете получить теневой ресурс приложения ввода-вывода Google здесь: https://github.com/google/iosched/blob/master/android/src/main/res/drawable-xxhdpi/bottom_shadow.9.png

Для устройств 5.0 и более поздних версий используйте /values-v21/styles.xml, чтобы добавить высоту на панель инструментов, используя собственный стиль заголовка:

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

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

Обратите внимание , что во втором случае я должен был создать пустой MyViewArea стиль так windowContentOverlay не будет отображаться слишком.

[Обновление: изменены имена ресурсов и добавлена ​​тень Google.]


Могу ли я узнать, что такое MyBody и MyHeader? Где я должен их применять?
— Чеок Ян Ченг

Я обновил имена: MyHeader теперь MyToolbar, а MyBody - MyViewArea. Вы можете назначить стили в макетах XML следующим образом: style = "@ style / MyToolbar".
— Рэдли

Для чего применяется MyViewArea?
— Зак Сперске

Ваша страница / тело / область просмотра.
— Рэдли

Я думаю, что android:foregroundработает только на FrameLayout до API 23.
— androidguy

14

Это сработало для меня очень хорошо:

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

Как это может работать, если на предварительных картах для леденцов сам по себе для рисования тени? Вот что я получаю: i.imgur.com/BIj8env.png этот ответ сработал для меня, и он не страдает от недостатков этого: stackoverflow.com/questions/26575197/…
— Aspiring Dev

2
На самом деле, вам лучше использовать AppBarLayout, как в этом ответе stackoverflow.com/a/31026359/1451716 Мой ответ старый, до того как AppBarLayout был выпущен
— Ислам А. Хасан

Это даже законно? Он не должен использоваться с панелью инструментов. О, МОЙ БОГ!
— user155

12

Если вы устанавливаете ToolBarкак, ActionBarтогда просто позвоните:

getSupportActionBar().setElevation(YOUR_ELEVATION);

Примечание: это должно быть вызвано после setSupportActionBar(toolbar);


1
Это только у меня, или навигационный ящик сбрасывает высоту панели инструментов? Я пытался установить его на 0, и это сработало, но потом, когда я перетаскиваю навигационную панель, я снова вижу тень ...
— Разработчик Android

6
setElevation()определяется только для API-21 +.
— Субин Себастьян

@Sebastian Поддержка высота панели действий работает и для предыдущих API.
— Роберто Б.

2
Внутренне это использует ViewCompat.setElevation()и, следовательно, будет работать только на API 21 и выше.
— botteaap

Используйте android: windowContentOverlay или android: передний план для API 21.
— Радли

9

я добавил

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

в описании панели инструментов, и это работает для меня. Используя 5.0+


7

Моя проблема заключается в том, что панель инструментов не отбрасывает тени, если я не установил атрибут «Высота». Это нормальное поведение или я что-то не так делаю?

Это нормальное поведение. Также смотрите FAQ в конце этого поста .


7

Несколько часов играл с этим, вот что сработало для меня.

Удалить все elevationатрибуты из appBarLayoutи Toolbarвиджетов ( в том числе , styles.xmlесли вы подаете любой стиль).

Теперь внутри деятельности, примените elvationна ваш actionBar:

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

Это должно работать.


Что делать, если я хочу повышения на AppBarLayout, так как он может разворачиваться / разворачиваться?
— разработчик Android

1
setElevationпринимает параметр в виде пикселей. Вы должны преобразовать его соответствующим образом, например,(int) (3.0 / Resources.getSystem().getDisplayMetrics().density)
— Ely

4

Вы также можете заставить его работать RelativeLayout. Это немного уменьшает вложенность макета;)

<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

Все, что вам нужно, android:margin_bottomравно android:elevationзначению. Нет AppBarLayout, clipToPaddingи т.д. требуется.

Пример:

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

ничего не сработало, кроме этого,
— точно

1

Для 5.0+: вы можете использовать AppBarLayout с панелью инструментов. AppBarLayout имеет атрибут "возвышение".

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

А как насчет предыдущих версий?
— разработчик 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>

добавить к фону 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>

имя = "displayOptions"> useLogo | showHome | ShowTitle | showCustom

добавить в 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

Большинство решений отлично работают здесь. Хотелось бы показать другую, похожую альтернативу:

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'

Ваш макет может иметь вид панели инструментов, и тень для него ниже, похожая на эту (конечно, нужно изменить):

<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 / вытяжка-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"/>

Рез / рисуем / 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"/>

Рез / рисуем / 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)
    }
}

Полный пример здесь , как я заметил, в IDE есть ошибка, связанная с тем, что foregroundатрибут слишком новый для использования здесь.


0

У меня была похожая проблема с тенью. В моем случае тень рисуется прямым родителем AppBarLayout. Если высота родительского элемента совпадает с высотой AppBarLayout, тень не может быть нарисована. Таким образом, проверка размера родительского макета и, возможно, римейк макета может решить проблему. https://www.reddit.com/r/androiddev/comments/6xddb0/having_a_toolbar_as_a_fragment_the_shadow/


0

Правильный ответ
: добавить android: backgroundTint = "# ff00ff" на панель инструментов с android: background = "@ android: color / white"

Если вы используете другой цвет, то белый для фона, он удалит тень. Хороший Google!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.