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


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.