Android "висота" не показує тіні


273

У мене є ListView, і з кожним елементом списку я хочу, щоб він відображав тінь під ним. Я використовую нову функцію підйому Android Lollipop, щоб встановити Z на вигляд, який я хочу кинути тінню, і це вже роблю ефективно з ActionBar (технічно Панель інструментів у Lollipop). Я використовую висоту Lollipop, але вона чомусь не відображає тінь під елементами списку. Ось як налаштовано макет кожного списку:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    style="@style/block"
    android:gravity="center"
    android:layout_gravity="center"
    android:background="@color/lightgray"
    >

    <RelativeLayout
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_marginLeft="40dp"
        android:layout_marginRight="40dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:elevation="30dp"
        >

        <ImageView
            android:id="@+id/documentImageView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop" />

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/alphared"
            android:layout_alignParentBottom="true" >

            <appuccino.simplyscan.Extra.CustomTextView
                android:id="@+id/documentName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/white"
                app:typeface="light"
                android:paddingLeft="16dp"
                android:paddingTop="8dp"
                android:paddingBottom="4dp"
                android:singleLine="true"
                android:text="New Document"
                android:textSize="27sp"/>

            <appuccino.simplyscan.Extra.CustomTextView
                android:id="@+id/documentPageCount"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/white"
                app:typeface="italic"
                android:paddingLeft="16dp"
                android:layout_marginBottom="16dp"
                android:text="1 page"
                android:textSize="20sp"/>

        </LinearLayout>

    </RelativeLayout>

</RelativeLayout>

Однак ось, як це відображається елемент списку, без тіні: введіть тут опис зображення

Я також спробував наступне безрезультатно:

  1. Встановіть висоту на самі ImageView та TextViews замість батьківського макета.
  2. Застосував фон до ImageView.
  3. Використаний TranslationZ замість висоти.

Я спробував ваш макет (без користувальницьких переглядів) і показав тінь у своєму телефоні, чи можете ви поділитися мінімальним проектом, який відтворює проблему?
rnrneverdies

1
можливий дублікат тіні кнопки Android L FAB
naveejr

Пов'язаний питання: stackoverflow.com/questions/26572048 / ...
stefan222

Відповіді:


383

Я трохи розігрувався з тінями на Lollipop, і ось що я знайшов:

  1. Схоже, батьківські ViewGroupмежі чомусь обрізають тінь своїх дітей; і
  2. тіні, встановлені з, android:elevationє обрізаними Viewмежами, а не межами, розширеними через поле;
  3. правильний спосіб отримати уявлення про дитину, щоб показати тінь, - це встановити накладку на батьківську і встановити android:clipToPadding="false"на цього батьківського.

Ось моя пропозиція до вас на основі того, що я знаю:

  1. Встановіть на верхньому рівні так, RelativeLayoutщоб підкладка дорівнювала встановленим полям у відносному макеті, який ви хочете показати тінню;
  2. встановити android:clipToPadding="false"на те саме RelativeLayout;
  3. Зніміть поле з того, RelativeLayoutщо також встановлено висоту;
  4. [EDIT] також може знадобитися встановити непрозорий колір фону на дочірньому макеті, який потребує висоти.

Наприкінці дня ваше відносне розташування верхнього рівня має виглядати так:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    style="@style/block"
    android:gravity="center"
    android:layout_gravity="center"
    android:background="@color/lightgray"
    android:paddingLeft="40dp"
    android:paddingRight="40dp"
    android:paddingTop="20dp"
    android:paddingBottom="20dp"
    android:clipToPadding="false"
    >

Внутрішня відносна компоновка повинна виглядати приблизно так:

<RelativeLayout
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:background="[some non-transparent color]"
    android:elevation="30dp"
    >

8
Дякую за це! Я також виявив, що android: clipChildren = "false" є корисним при застосуванні до батьківського відносного макета.
блаффі

1
Радий допомогти @blaffie!
Джастін Поллард

214
Це настільки дратує, що Google виробляє такий недбалий код. Нам доведеться відповідати за ці рамкові помилки роками.
Мігель

8
Google каже лише (на жаль): " Тіні намальовані батьком підвищеного виду, і, таким чином, вони підлягають стандартному відсіченню перегляду, обрізаному батьківським за замовчуванням. "
Джон

5
У моєму випадку це був прозорий колір. Ок, прозорі речі не кидають тіней ... ха-ха
Ферран Мейлінч

285

Якщо у вас перегляд не має фону, ця лінія вам допоможе

android:outlineProvider="bounds"

За замовчуванням тінь визначається фоном перегляду, тому, якщо немає фону, не буде й тіні.


11
Що дивно, Preview показав висоту, але справжній пристрій цього не зробив. Дякую, це вирішило проблему.
Іоан Шарвадзе

Працює для рівня 21 і вище
Pantelis Ieronimakis

10
Цей вид працював для мене, але давав діагональну межу з боків при застосуванні до перегляду тексту. Налаштування фону на колір (такий же, як і фоновий колір батьків) працював краще.
Гобер

4
Це також застосовується, якщо ваш фон є спеціальним і не має <solid>.
Девід Лорд

Це можна використовувати в зворотному порядку. Коли ви хочете непрозорий фон з піднесенням і не хочете тіні. Просто встановіть його none. Дякую!
Одіс

101

Судячи з усього, ви не можете просто встановити висоту на виду і відобразити його. Також потрібно вказати фон.

Наступні рядки, додані до мого LinearLayout, нарешті показали тінь:

android:background="@android:color/white"
android:elevation="10dp"

Це було несподівано. Я встановив ImageView з src і шукав рішення. Дякую.
Андрій Росте

47

ще одна річ, про яку слід пам’ятати, тіні не відображатимуться, якщо ви маєте цей рядок у маніфесті:

android: hardwareAccelerated = "помилково"

Я спробував усі запропоновані речі, але він працював для мене лише тоді, коли я видалив лінію, тому у мене з'явилася лінія, тому що мій додаток працює з кількома растровими зображеннями, і вони спричиняють збій програми.


1
Це не вирішує проблему, якщо вам потрібен цей прапор.
Клайв Джеффріс

спасибі!! Я провів день, намагаючись підняти AppBar, і виявив проблему, коли перевірив маніфест на цей прапор діяльності
ir2pid

1
Я спробував усі можливі рішення, але для мене нічого не вийшло. Це рішення спрацювало. Дякую. Також потрібно android:clipToPadding="false"з цим рішенням.
Чираг Савсані

29

Якщо у вас перегляд не має фону, ця лінія вам допоможе

android:outlineProvider="bounds"

Якщо у вас є вид з фоном, цей рядок вам допоможе

android:outlineProvider="paddedBounds"

6
Це рішення - єдине, що працює для мене. Дякую
Олег Лиськович

4
Це працює, якщо у вас немає радіусу на тлі перегляду, і в цьому випадку тінь буде відображатися як прямокутна, але paddedBounds не працює для подання з фоном.
Тревор Харт

android:outlineProvider="paddedBounds"ця лінія працювала на мене. Я встановив Selector Dravable.
Chirag Savsani

1
Коли я використовував це, тінь малюється повністю всередині зору, а не зовні, що не те, що я хочу.
androidguy


12

Фу, щойно витратив годину, намагаючись розібратися в цьому. У моєму випадку у мене був набір фону, проте він був встановлений у кольорі. Цього недостатньо, потрібно мати фон перегляду встановленим на малюнок.

Наприклад, це не матиме тіні:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="165dp"
    android:background="@color/ight_grey"
    android:elevation="20dp"
    android:orientation="vertical"
    />

але це буде

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="165dp"
    android:background="@drawable/selector_grey"
    android:elevation="20dp"
    android:orientation="vertical"
    />

РЕДАКТУВАННЯ. Також вияснили, що якщо ви використовуєте селектор як фон, якщо у вас немає кута, тоді тінь не з’явиться у вікні попереднього перегляду, але він з’явиться на пристрої

Наприклад, у попереднього перегляду немає тіні:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/white" />
            <stroke
                android:width="1dp"
                android:color="@color/grey"/>
        </shape>
    </item>
</selector>

але це робить:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/white" />
            <corners android:radius="1dp" />
            <stroke
                android:width="1dp"
                android:color="@color/grey"/>
        </shape>
    </item>
</selector>

1
Точно протилежне вашому першому моменту було справжнім для мене в пункті RecyclerView ... Дивно, як я все-таки знаходжу випадки, коли мені доводиться битися з цими API після 5 років професійної розробки Android :(
aProperFox

7

Додавання фонового кольору допомогло мені.

<CalendarView
    android:layout_width="match_parent"
    android:id="@+id/calendarView"
    android:layout_alignParentTop="true"
    android:layout_alignParentStart="true"
    android:layout_height="wrap_content"
    android:elevation="5dp"

    android:background="@color/windowBackground"

    />

4

Іноді подобається background="@color/***"чи background="#ff33**"не працює, я background_colorзамінюю на малювання, тоді воно працює


4

Якщо вона все ще не показує висоту, спробуйте

    android:hardwareAccelerated="true" 

це вам точно допоможе.


Це зафіксувало це для мене. Я припускав, що TRUE - це налаштування за замовчуванням, але, мабуть, ні, принаймні в моєму випадку.
Метт Робертсон

3

Якщо ви хочете мати прозорий фон і android:outlineProvider="bounds"не працює для вас, ви можете створити спеціальний ViewOutlineProvider:

class TransparentOutlineProvider extends ViewOutlineProvider {

    @Override
    public void getOutline(View view, Outline outline) {
        ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
        Drawable background = view.getBackground();
        float outlineAlpha = background == null ? 0f : background.getAlpha()/255f;
        outline.setAlpha(outlineAlpha);
    }
}

І встановіть цього постачальника на ваш прозорий вигляд:

transparentView.setOutlineProvider(new TransparentOutlineProvider());

Джерела: https://code.google.com/p/android/isissue/detail?id=78248#c13

[EDIT] Документація Dravable.getAlpha () говорить, що це специфічно для того, як Dravable загрожує альфа. Можливо, що він завжди буде повертати 255. У цьому випадку ви можете надати альфа вручну:

class TransparentOutlineProvider extends ViewOutlineProvider {

    private float mAlpha;

    public TransparentOutlineProvider(float alpha) {
        mAlpha = alpha;
    }

    @Override
    public void getOutline(View view, Outline outline) {
        ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
        outline.setAlpha(mAlpha);
    }
}

Якщо тло перегляду - це StateListDrawable із кольором за замовчуванням # DDFF0000, тобто з альфа-DDx0 / FFx0 == 0,86

transparentView.setOutlineProvider(new TransparentOutlineProvider(0.86f));

2

дати деякий колір тла для компонування, який працював для мене, як:

    android:background="@color/catskill_white"
    android:layout_height="?attr/actionBarSize"
    android:elevation="@dimen/dimen_5dp"

1

Мені пощастило з налаштуванням clipChildren="false"на батьківський макет.


1

Я провів деякий час над цим, і нарешті зрозумів, що коли фон темний, тіні не видно


1

Додаючи до прийнятої відповіді, є ще одна причина, через яку висота може не працювати, як очікувалося, якщо функція фільтра Bluelight на телефоні увімкнена.

Я стикався з цим питанням, коли висота виявилася повністю спотвореною і нестерпною в моєму пристрої. Але висота була прекрасною у попередньому перегляді. Вимкнення фільтра Bluelight на телефоні вирішило проблему.

Так що навіть після встановлення

android:outlineProvider="bounds"

Висота не працює належним чином, тоді ви можете спробувати познайомитися з налаштуваннями кольору телефону.


0

Я вважаю, що ваше питання випливає з того, що ви застосували елемент елевації до відносного макета, який заповнює його батьківський. Його батько обрізає всі дитячі погляди в межах власного полотна для малювання (і це вид, який обробляє тінь дитини). Ви можете виправити це, застосувавши властивість елевації до самого верхнього RelativeLayoutу вашому представленні xml (кореневий тег).


0

У моєму випадку проблема була шрифтами.

1) Без fontFamilyмене потрібно було встановити android:backgroundякесь значення.

<TextView
    android:layout_width="match_parent"
    android:layout_height="44dp"
    android:background="@android:color/white"
    android:elevation="3dp"
    android:gravity="center"
    android:text="@string/fr_etalons_your_tickets"
    android:textAllCaps="true"
    android:textColor="@color/blue_4" />

2) з fontFamilyмені довелося додати android:outlineProvider="bounds"налаштування:

<TextView
    android:fontFamily="@font/gilroy_bold"
    android:layout_width="match_parent"
    android:layout_height="44dp"
    android:background="@android:color/white"
    android:elevation="3dp"
    android:gravity="center"
    android:outlineProvider="bounds"
    android:text="@string/fr_etalons_your_tickets"
    android:textAllCaps="true"
    android:textColor="@color/blue_4" />

0

У моєму випадку це було спричинено тим, що користувацький компонент-батько встановив тип шару візуалізації на "Програмне забезпечення":

setLayerType(View.LAYER_TYPE_SOFTWARE, null);

Видалення цієї лінії зробило трюк. Або, звичайно, потрібно оцінити, чому це в першу чергу. У моєму випадку це було підтримати Honeycomb, що значно відстає від мінімального мінімуму SDK для мого проекту.


0

Також перевірте, чи ви не змінюєте альфа в цьому вікні. Я досліджую проблему, коли я змінюю альфа на деяких поглядах, з висотою. Вони просто втрачають висоту, коли альфа змінюється і змінюється назад до 1f.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.