На панелі інструментів за замовчуванням немає тіні?


165

Я оновлюю свою програму новою Панеллю інструментів з бібліотеки підтримки v21. Моя проблема полягає в тому, що на панелі інструментів не залишається тіні, якщо я не встановив атрибут "elevation". Це нормальна поведінка чи я щось роблю неправильно?

Мій код:

<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, відображається тінь через атрибут elevation, але не в KitKat або старіших версіях. Така очікувана поведінка для атрибута елевації, як говорить документація, але я очікував, що за замовчуванням без атрибута елевації тінь буде кидатися так, як це робиться панель дій у кожній версії.
MrBrightside

Тут я розмістив можливе рішення: stackoverflow.com/a/26759202/553905
Біллі

Використовуйте / value folders and styles.xml, щоб застосувати належний тіньовий код на основі версії ОС (див. Нижче).
radley

Відповіді:


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>

@ dravable / 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>

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


3
Не забудьте приховати свій погляд, якщо пристрій, на якому ви працюєте, перебуває> = Lollipop, якщо ні, ви отримаєте дві тіні.
mradzinski

1
Це неправильний шлях до цього, оскільки вам доведеться видалити цей вид для 5.0 макетів. Використовуйте замість android: windowContentOverlay або android: foreground.
radley

3
Компанія Google про розробку дизайну матеріалів на Панелі інструментів вам слід встановити android:layout_height="4dp"висоту тіні, а не висоту тіні 5dp. Власне, висота така ж, як і висота тіні, яку ви встановили FrameLayout.
Anggrayudi H

2
У мене виникають проблеми з цим рішенням, оскільки я завищую макет своєї діяльності в макет кадру у вашому прикладі, чи можете ви придумати спосіб, як це вдасться?
Zach Sperske

2
Рекомендую використовувати "android: endColor =" # c7c7c7 "для android: endColor =" # 88333333 "
Mohammad Faisal

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
Вам не потрібні ці два рядки компілювати 'com.android.support:support-v4:22.2.0' компілювати 'com.android.support:appcompat-v7:22.2.0', тому що компілювати 'com.android.support: дизайн: 22.2.0 'залежить від них
Андрій

8
Зауважте, це працює лише для льодяника та вище. Він не працюватиме попередньо льодяником, оскільки під ним просто використовується ViewCompat.setElevation ().
Амірул Зін

25

Ви не можете використовувати атрибут elevation перед 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" />

@ dravable / 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 / панелі інструментів є два види кореня? Чи можете ви надати повний приклад, будь ласка?
RED_

18

Використовуйте папки / значень, щоб застосувати правильний стиль тіні на основі версії ОС.

Для пристроїв під 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>

Ви можете захопити тіньовий ресурс програми IO Google тут: https://github.com/google/iosched/blob/master/android/src/main/res/dravable-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, щоб вікноContentOverlay теж не відображалося.

[Оновлення: змінено імена ресурсів та додано тінь Google.]


Чи можу я знати, що таке MyBody та MyHeader? Де я повинен їх застосувати?
Чак Ян Чен

Я оновив імена: MyHeader зараз MyToolbar, а MyBody - MyViewArea. Ви можете призначити стилі у форматі xml таким чином: style = "@ style / MyToolbar".
радлей

До чого застосовується MyViewArea?
Zach Sperske

Ваша сторінка / тіло / область перегляду.
radley

Думаю, 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/…
прагнув Dev

2
Насправді, вам краще з AppBarLayout, як у цій відповіді stackoverflow.com/a/31026359/1451716 Моя відповідь стара, до виходу AppBarLayout
Іслам А. Хасан

Це навіть законно? Його не слід використовувати з Панеллю інструментів. О БОЖЕ МІЙ!
користувач155

12

Якщо ви сідаєте ToolBarтак, ActionBarпросто зателефонуйте:

getSupportActionBar().setElevation(YOUR_ELEVATION);

Примітка. Це потрібно викликати після setSupportActionBar(toolbar);


1
Це тільки я, або ящик навігації скидає висоту панелі інструментів? Я намагався встановити його на 0, і це спрацювало, але потім, коли я перетягую навігаційний ящик, я бачу, що він знову має тінь ...
android developer

6
setElevation()визначається лише для API-21 +.
Субін Себастьян

@Sebastian Підвищення панелі дій працює і для попередніх API.
Роберто Б.

2
Внутрішнє, що використовує ViewCompat.setElevation()і, таким чином, працюватиме лише на API 21 і новіших версій.
botteaap

Використовуйте android: windowContentOverlay або android: передній план для API 21.
radley

9

я додав

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

в описі панелі інструментів, і це працює для мене. Використання 5.0+


7

Моя проблема полягає в тому, що на панелі інструментів не залишається тіні, якщо я не встановив атрибут "elevation". Це нормальна поведінка чи я щось роблю неправильно?

Це нормальна поведінка. Також дивіться поширені запитання в кінці цієї публікації .


7

Години грався з цим, ось що для мене спрацювало.

Видалити всі elevationатрибути з appBarLayoutі Toolbarвіджетів ( в тому числі , styles.xmlякщо ви подаєте будь-який стиль).

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

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

Це має спрацювати.


Що робити, якщо я хочу висоти на AppBarLayout, оскільки вона може згортатися / розширюватися?
андроїд розробник

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>

Що з попередніми версіями?
андроїд розробник

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>

name = "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 / dravable-v21 / панель інструментів washing_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 / dravable / панель інструментів washing_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 / dravable / 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.