Reputation: 10352
I am trying to make use of the elevation property in the latest Android Lollipop preview release. I set the targetSdk to 21 and the theme to Material. Next i added a background shape to a TextView and set the elevation to 8dp but the TextView is not showing any signs of a shadow. That is on a Nexus7 running the Lollipop preview. Is there anything else i have to consider?
Here is the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/rect"
android:text="hallo world"
android:padding="8dp"
android:elevation="8dp" />
</LinearLayout>
This is the background drawable:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#7d0073ff" />
<corners android:radius="16dp" />
</shape>
Here is the TextView:
Upvotes: 28
Views: 39368
Reputation: 1512
be aware, if you have the following line in the manifest then shadows wont show:
android:hardwareAccelerated="false"
Upvotes: 4
Reputation: 4166
As noted earlier, this is an open bug in Android : if the background drawable uses a solid color with transparency, then the shadow won't be shown.
To work around the issue, display the background in its own separate view and set the alpha on that view. Wrap the background view and the TextView
in a RelativeLayout
to place the background directly under the TextView
and use android:layout_alignLeft
, android:layout_alignBottom
etc to make it the same size. They need to be at the same elevation, and the background must appear before the TextView
in the xml so it is drawn under it.
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="40dp"
android:paddingRight="40dp"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:clipToPadding="false"
android:background="#ffffff">
<View
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/text_view"
android:layout_alignRight="@id/text_view"
android:layout_alignBottom="@id/text_view"
android:layout_alignTop="@id/text_view"
android:background="@drawable/rect"
android:alpha="0.5"
android:elevation="8dp"/>
<TextView
android:id="@id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hallo world"
android:textColor="#ffffff"
android:padding="8dp"
android:elevation="8dp" />
</RelativeLayout>
The drawable is the same as yours but without transparency:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#0073ff" />
<corners android:radius="16dp" />
</shape>
Result:
A few notable points:
RelativeLayout
is large enough to display the shadow. If you just set its dimensions to wrap_content
without padding, the shadow will be clipped to the layout's bounds. As explained in this question, you can use padding and set android:cipToPadding="false"
to make it large enough for the shadow. You might not need as much padding in this case, I haven't experimented with that.alpha
directly on the TextView
then the text would have been affected as well. Depending on your use case you might not need a separate view and enclosing layout and could just just have one view, with alpha
set on the view and no transparency in the drawable.Upvotes: 2
Reputation: 3421
TL;DR
Check your card: (or whatever word you use) namespace declaration and make sure it matches this: xmlns:card="http://schemas.android.com/apk/res-auto"
I know there are a few answers here already, but I wanted to add mine as it wasn't included in these current suggestions. In order to get the shadows working on both KitKat and Marshmallow, (only emulators I tried, I'm sure it works in between) I added the following xml attributes to my card:
card:cardElevation="25dp"
card:cardUseCompatPadding="true"
After banging my head against my desk for why that wasn't working, trying to set the background color of the card to something completely opaque, enabling hardware acceleration in the manifest, and even praying, I checked the namespace declarations in my file. To my horror, I saw that the card xml namespace had been assigned to the following:
xmlns:card="http://schemas.android.com/tools"
After fixing that namespace declaration, I ran my dummy app again and let out a sigh of relief as shadows were finally being shown as expected.
Here is proof in case you're a doubter like me. And please Google, Android, whoever: Make shadows great again. They shouldn't be this difficult.
Here is the entire file that created the layout pictured below:
<?xml version="1.0" encoding="utf-8"?>
<!--MAKE SURE YOU HAVE THE RIGHT XML NAMESPACE ASSIGNED-->
<!--TO WHATEVER WORD YOU PUT IN FRONT OF THE CARD-->
<!--XML ATTRIBUTES. IN THIS CASE, MINE IS card-->
<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#607D8B"
android:fitsSystemWindows="true"
tools:context="com.mlustig.playground.MainActivity">
<android.support.v7.widget.CardView
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
app:layout_aspectRatio="66%"
app:layout_heightPercent="75%"
card:cardElevation="25dp"
card:cardUseCompatPadding="true" />
</android.support.percent.PercentRelativeLayout>
Yes, I know. It's annoying that you can't simply copy and paste this layout and run it because it has PercentRelativeLayout in it, but I left it there on purpose. You should definitely check it out. Super powerful, very useful. Nice nice nice. Hope this helped.
Upvotes: 3
Reputation: 1025
ADDING android:elevation shadow to an ImageView:
android:clipToPadding="false"
+
android:outlineProvider="bounds"
+
android:elevation="2dp"
Upvotes: 17
Reputation: 2025
I was also having this problem, and as it turns out, you need to turn hardware acceleration on in the android manifest
<application
...
android:hardwareAccelerated="true">
Upvotes: 9
Reputation: 16664
After going through the docs again, I finally found the solution.
Just add card_view:cardUseCompatPadding="true"
to your CardView
and shadows will appear on Lollipop devices.
What happens is, the content area in a CardView
take different sizes on pre-lollipop and lollipop devices. So in lollipop devices the shadow is actually covered by the card so its not visible. By adding this attribute the content area remains the same across all devices and the shadow becomes visible.
My xml code is like :
<android.support.v7.widget.CardView
android:id="@+id/media_card_view"
android:layout_width="match_parent"
android:layout_height="130dp"
card_view:cardBackgroundColor="@android:color/white"
card_view:cardElevation="2sp"
card_view:cardUseCompatPadding="true"
>
...
</android.support.v7.widget.CardView>
Upvotes: 18
Reputation: 10552
For some reason if you set a solid color with a transparency, the elevation shadow does not show up.
In your example, I changed #7d0073ff to #0073ff and I got a shadow.
This is probably a bug, as in their documentation it gives a similar example using a translucent background color.
Upvotes: 61