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.