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


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.