Android "высота" не показывает тень

У меня есть 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 вместо Elevation.

23 ответа

Решение

Я немного поигрался с тенями на 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"
    >

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

android:outlineProvider="bounds"

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

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

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

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

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

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

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

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

android:outlineProvider="bounds"

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

android:outlineProvider="paddedBounds"

Если вы добавляете высоту к элементу кнопки, вам нужно добавить следующую строку:

android:stateListAnimator="@null"

См. Android 5.0 android: высота работает для просмотра, но не кнопка?

Тьфу, просто провел час, пытаясь понять это. В моем случае у меня был установлен фон, но он был установлен на цвет. Этого недостаточно, вам нужно установить фон вида для рисования.

Например, это не будет иметь тени:

<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>

Добавление цвета фона помогло мне.

<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"

    />

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

Если на телефоне включена функция фильтра Bluelight

Я столкнулся с этой проблемой, когда высота была совершенно искажена и невыносима в моем устройстве. Но высота была хороша в предварительном просмотре. Отключение фильтра Bluelight на телефоне решило проблему.

Так что даже после настройки

android:outlineProvider="bounds"

Высота не работает должным образом, то вы можете попытаться повозиться с настройками цвета телефона.

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

    android:hardwareAccelerated="true" 

это определенно поможет вам.

Для меня настройка высоты, фона и поля работала как шарм.

      android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:background="@drawable/card_view" //any drawable or color
android:elevation="4dp"

Иногда, как background = "@ color /*" или background = "# ff33" не работает, я заменяю background_color на drawable, тогда он работает

Если вы хотите иметь прозрачный фон и 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

[РЕДАКТИРОВАТЬ] Документация 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));

Дать немного цвета фона, чтобы макет работал для меня, как:

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

Мне повезло с настройкой clipChildren="false" на родительском макете.

Я потратил некоторое время, работая над этим, и наконец понял, что, когда фон темный, тень не видна

Также проверьте, не меняете ли вы альфу в этом представлении. Я изучаю проблему, когда я меняю альфа-канал в некоторых представлениях с повышением. Они просто теряют высоту, когда альфа изменяется и возвращается к 1f.

В моем случае это было вызвано тем, что пользовательский родительский компонент установил тип слоя рендеринга в "Программное обеспечение":

setLayerType(View.LAYER_TYPE_SOFTWARE, null);

Удаление этой строчки сделало свое дело. Или, конечно, вы должны оценить, почему это происходит в первую очередь. В моем случае это была поддержка Honeycomb, которая значительно отстает от текущего минимального SDK для моего проекта.

Я полагаю, что ваша проблема связана с тем фактом, что вы применили элемент высот к относительному макету, который заполняет его родительский элемент. Его родитель обрезает все дочерние представления на своем собственном холсте рисования (и это представление, которое обрабатывает тень дочернего элемента). Вы можете исправить это, применив свойство возвышения к самому верхнему RelativeLayout на ваш взгляд xml (корневой тег).

Установка обоих clipChildren и clipToPadding в родительском макете помогла мне.

      android:clipChildren="false"
android:clipToPadding="false"

В моем случае шрифты были проблемой.

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" />

Установить цвет фона для макета или представления

Установка android:clipToPadding="false" в верхнем относительном макете решила проблему.

Другие вопросы по тегам