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
возможная
— копия

Похожий вопрос: stackoverflow.com/questions/26572048/…
— stefan222

Ответы:


384

Я немного поигрался с тенями на Lollipop, и вот что я нашел:

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

Вот мое предложение для вас на основе того, что я знаю:

  1. Установите верхний уровень так, RelativeLayoutчтобы отступы были равны полям, установленным для относительного макета, для которого вы хотите показать тень;
  2. установить android:clipToPadding="false"на то же самое RelativeLayout;
  3. Удалить поле из того, RelativeLayoutчто также имеет набор высоты;
  4. [РЕДАКТИРОВАТЬ] вам также может потребоваться установить непрозрачный цвет фона для дочернего макета, который требует повышения.

В конце дня ваш относительный макет верхнего уровня должен выглядеть следующим образом:

<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
В моем случае это был прозрачный цвет. Хорошо, прозрачные вещи не отбрасывают тени ... ха-ха
— Ферран Майлинч

286

Если у вас есть вид без фона, эта строка поможет вам

android:outlineProvider="bounds"

По умолчанию тень определяется фоном вида, поэтому, если фон отсутствует, тени также не будет.


11
Какая странная вещь, превью показало повышение, но реальное устройство не Спасибо, этот исправил проблему.
— Иоанн Шарвадзе

Работает на уровне API 21 и выше
— Pantelis Ieronimakis

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

4
Это также применимо, если ваш фон настроен и не имеет <solid>.
— Дэвид Лорд

Это может быть использовано в обратном порядке. Когда вы хотите непрозрачный фон с возвышением и не хотите тени. Просто установите это none. Спасибо!
— Одис

101

По-видимому, вы не можете просто установить высоту в представлении, чтобы оно появилось. Вам также необходимо указать фон.

Следующие строки, добавленные в мой LinearLayout, наконец-то показали тень:

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

Это было неожиданно. Я установил ImageView с src и искал решение. Спасибо.
— Эндрю Гроу

47

еще одна вещь, о которой вы должны знать, тени не будут отображаться, если у вас есть эта строка в манифесте:

андроид: hardwareAccelerated = "ложь"

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


1
Это не решает проблему, если вам нужен этот флаг.
— Клайв Джефферис

Спасибо!! Я провел день, пытаясь поднять AppBar, и обнаружил проблему, когда проверил манифест на наличие этого флага активности
— ir2pid

1
Я перепробовал все возможные решения, но ни один из них не помог мне. Это решение работало. Спасибо. Также нужно android:clipToPadding="false"с этим решением.
— Чираг Савсани

29

Если у вас есть вид без фона, эта строка поможет вам

android:outlineProvider="bounds"

Если у вас есть вид с фоном, эта строка поможет вам

android:outlineProvider="paddedBounds"

6
Это единственное решение, которое работает для меня. Спасибо
— Олег Лискович

4
Это работает, если у вас нет радиуса на фоне ваших представлений, в этом случае тень будет отображаться как прямоугольник, но paddedBounds действительно работает для вида с фоном.
— Тревор Харт

android:outlineProvider="paddedBounds"эта линия работала для меня. Я установил селектор Drawable.
— Чираг Савсани

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на drawable, потом работает


4

Если это все еще не показывает высоту, попробуйте

    android:hardwareAccelerated="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/issues/detail?id=78248#c13

[РЕДАКТИРОВАТЬ] Документация Drawable.getAlpha () говорит, что это зависит от того, как Drawable угрожает альфа. Вполне возможно, что он всегда будет возвращать 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.