'Android "elevation" not showing a shadow
I have a ListView, and with each list item I want it to show a shadow beneath it. I am using Android Lollipop's new elevation feature to set a Z on the View that I want to cast a shadow, and am already doing this effectively with the ActionBar (technically a Toolbar in Lollipop). I am using Lollipop's elevation, but for some reason it isn't showing a shadow under the list items. Here is how each list item's layout is set up:
<?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>
However, here is how it shows the list item, without a shadow:
I have also tried the following to no avail:
- Set the elevation to the ImageView and TextViews themselves instead of the parent layout.
- Applied a background to the ImageView.
- Used TranslationZ in place of Elevation.
Solution 1:[1]
I've been playing around with shadows on Lollipop for a bit and this is what I've found:
- It appears that a parent
ViewGroup
's bounds cutoff the shadow of its children for some reason; and - shadows set with
android:elevation
are cutoff by theView
's bounds, not the bounds extended through the margin; - the right way to get a child view to show shadow is to set padding on the parent and set
android:clipToPadding="false"
on that parent.
Here's my suggestion to you based on what I know:
- Set your top-level
RelativeLayout
to have padding equal to the margins you've set on the relative layout that you want to show shadow; - set
android:clipToPadding="false"
on the sameRelativeLayout
; - Remove the margin from the
RelativeLayout
that also has elevation set; - [EDIT] you may also need to set a non-transparent background color on the child layout that needs elevation.
At the end of the day, your top-level relative layout should look like this:
<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"
>
The interior relative layout should look like this:
<RelativeLayout
android:layout_width="300dp"
android:layout_height="300dp"
android:background="[some non-transparent color]"
android:elevation="30dp"
>
Solution 2:[2]
If you have a view with no background this line will help you
android:outlineProvider="bounds"
By default shadow is determined by view's background, so if there is no background, there will be no shadow also.
Solution 3:[3]
Apparently, you cannot just set an elevation on a View and have it appear. You also need to specify a background.
The following lines added to my LinearLayout finally showed a shadow:
android:background="@android:color/white"
android:elevation="10dp"
Solution 4:[4]
one other thing that you should be aware of, shadows will not show if you have this line in the manifest:
android:hardwareAccelerated="false"
I tried all of the suggested stuff but it only worked for me when i removed the line, the reason i had the line was because my app works with a number of bitmap images and they were causing the app to crash.
Solution 5:[5]
If you have a view with no background this line will help you
android:outlineProvider="bounds"
If you have a view with background this line will help you
android:outlineProvider="paddedBounds"
Solution 6:[6]
If you are adding elevation to a button element, you need to add the following line:
android:stateListAnimator="@null"
See Android 5.0 android:elevation Works for View, but not Button?
Solution 7:[7]
Ugh, just spent an hour trying to figure this out. In my case I had a background set, however it was set to a color. This is not enough, you need to have the background of the view set to a drawable.
e.g. This won't have a shadow:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="165dp"
android:background="@color/ight_grey"
android:elevation="20dp"
android:orientation="vertical"
/>
but this will
<LinearLayout
android:layout_width="match_parent"
android:layout_height="165dp"
android:background="@drawable/selector_grey"
android:elevation="20dp"
android:orientation="vertical"
/>
EDIT: Have also discovered that if you use a selector as a background, if you don't have the corner set then the shadow won't show up in the Preview window but it will show up on the device
e.g. This doesn't have a shadow in preview:
<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>
but this does:
<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>
Solution 8:[8]
Adding background color helped me.
<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"
/>
Solution 9:[9]
Adding to the accepted answer, there is one more reason due to which elevation may not work as expected if the Bluelight filter feature on the phone is ON.
I was facing this issue when the elevation appeared completely distorted and unbearable in my device. But the elevation was fine in the preview. Turning off the Bluelight filter on phone resolved the issue.
So even after setting
android:outlineProvider="bounds"
The elevation is not working properly, then you can try to tinker with phone's color settings.
Solution 10:[10]
Sometimes like background="@color/***"
or background="#ff33**"
not work, I replace background_color
with drawable, then it works
Solution 11:[11]
If it still not showing elevation try
android:hardwareAccelerated="true"
this will definitely help you.
Solution 12:[12]
If you want to have transparent background and android:outlineProvider="bounds"
doesn't work for you, you can create custom 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);
}
}
And set this provider to your transparent view:
transparentView.setOutlineProvider(new TransparentOutlineProvider());
Sources: https://code.google.com/p/android/issues/detail?id=78248#c13
[EDIT] Documentation of Drawable.getAlpha() says that it is specific to how the Drawable threats the alpha. It is possible that it will always return 255. In this case you can provide the alpha manually:
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);
}
}
If your view background is a StateListDrawable with default color #DDFF0000 that is with alpha DDx0/FFx0 == 0.86
transparentView.setOutlineProvider(new TransparentOutlineProvider(0.86f));
Solution 13:[13]
give some background color to layout worked for me like:
android:background="@color/catskill_white"
android:layout_height="?attr/actionBarSize"
android:elevation="@dimen/dimen_5dp"
Solution 14:[14]
I had some luck with setting clipChildren="false"
on the parent layout.
Solution 15:[15]
I spent some time working on it and finally realized that when the background is dark, shadow is not visible
Solution 16:[16]
Also check if You don't change alpha on that view. I am investigating issue when i change alpha on some views, with elevation. They simply loose elevation when alpha is changed and changed back to 1f.
Solution 17:[17]
For me setting elevation, background and margin worked like a charm.
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:background="@drawable/card_view" //any drawable or color
android:elevation="4dp"
Solution 18:[18]
I believe your issue stems from the fact that you have applied the elevation element to a relative layout that fills its parent. Its parent clips all child views within its own drawing canvas (and is the view that handles the child's shadow). You can fix this by applying an elevation property to the topmost RelativeLayout
in your view xml (the root tag).
Solution 19:[19]
In my case fonts were the problem.
1) Without fontFamily
I needed to set android:background
to some value.
<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) with fontFamily
I had to add android:outlineProvider="bounds"
setting:
<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" />
Solution 20:[20]
In my case, this was caused by a custom parent component setting the rendering layer type to "Software":
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
Removing this line of did the trick. Or course you need to evaluate why this is there in the first place. In my case it was to support Honeycomb, which is well behind the current minimum SDK for my project.
Solution 21:[21]
Setting both clipChildren and clipToPadding on parent layout did the job for me
android:clipChildren="false"
android:clipToPadding="false"
Solution 22:[22]
Setting android:clipToPadding="false" in the top relative layout has solved the problem.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow