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>
Однако вот как он показывает элемент списка без тени:
Я также попробовал следующее безрезультатно:
- Установите высоту для самих ImageView и TextViews вместо родительского макета.
- Применил фон к ImageView.
- Используется TranslationZ вместо Elevation.
23 ответа
Я немного поигрался с тенями на Lollipop, и вот что я нашел:
- Похоже, что родитель
ViewGroup
по каким-то причинам отсекает тень своих детей; а также - тени установлены с
android:elevation
отрезаныView
границы, а не границы, простирающиеся через край; - правильный способ заставить дочерний вид показать тень, это установить отступы для родителя и установить
android:clipToPadding="false"
на этого родителя.
Вот мое предложение для вас на основе того, что я знаю:
- Установите свой верхний уровень
RelativeLayout
чтобы отступы были равны полям, которые вы установили для относительного макета, для которого вы хотите показать тень; - задавать
android:clipToPadding="false"
на том жеRelativeLayout
; - Удалить поле из
RelativeLayout
это также имеет набор высоты; - [РЕДАКТИРОВАТЬ] вам также может потребоваться установить непрозрачный цвет фона для дочернего макета, который требует повышения.
В конце дня ваш относительный макет верхнего уровня должен выглядеть следующим образом:
<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" в верхнем относительном макете решила проблему.