Reputation: 6462
I have a view that is to server as a footer title. It is just a view, that you may think of as a button or a textview or a layout (I am open to anything really). Here is the xml
<RelativeLayout>
<ScrollView >… </ScrollView> //match parent width and height
<MyBottomView/> // align parent bottom
</RelativeLayout>
So as you can see the ScrollView does scroll below MyBottomView. I want to add a top shadow to the MyBottomView so it looks more like Material Design. How might I do that?
Upvotes: 18
Views: 47293
Reputation: 18699
If you need to have shadow just on one side of the view (e.g. on top), you can add another View before it and use gradient shadow for its background.
Here is the gradient file top_shadow_gradient.xml
that you have to store in drawable
folder:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="90"
android:endColor="#30ffffff"
android:startColor="#40000000" />
</shape>
And here is a sample layout how to use it:
<?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"
android:background="@android:color/transparent"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="8dp"
android:background="@drawable/top_shadow_gradient" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:orientation="vertical"
android:paddingTop="8dp">
<!-- Put your content here-->
</LinearLayout>
</LinearLayout>
Important: The root layout have to be transparent (android:background="@android:color/transparent"
) and your "content" layout need to have white background (android:background="#ffffff"
).
Upvotes: 84
Reputation: 343
I have updated Ivo's excellent answer by including the use of ConstraintLayouts.
Drawable: shadow_top.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#40000000" android:endColor="#10ffffff" android:angle="90"/>
</shape>
Layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_topView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/cl_bottomView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
... nested views
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:id="@+id/v_shadowTop"
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="@drawable/shadow_top"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@id/cl_bottomView"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_bottomView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_topView">
... nested views
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Result: Following the steps above I was able to get the top shadow indicated by the arrow in the picture below.
For those newer to Android Development:
Height Adjustment: The height of the shadow is controlled by the view's, "v_shadowTop", height (currently 3dp).
Gradient Adjustment: The gradient's color is controlled by the last six characters (hex code) of the startColor (currently 000000) and endColor (currently ffffff) in the "shadow_top.xml" drawable.
The transparency is controlled by the first two characters of the startColor (currently 40) and endColor (currently 10) in the shadow_top.xml drawable.
Upvotes: 5
Reputation: 19351
Here are some solutions for this problem - choose your best:
There is no such attribute in Android, to show a shadow. But possible ways to do it are:
- Add a plain LinearLayout with grey color, over which add your actual layout, with margin at the bottom and right equal to 1 or 2 dp.
- Have a 9-patch image with a shadow and set it as the background to your Linear layout.
and
There is also another solution to the problem by implementing a layer-list that will act as the background for the LinearLayoout.
Add background_with_shadow.xml file to
res/drawable
. Containing:<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item > <shape android:shape="rectangle"> <solid android:color="@android:color/darker_gray" /> <corners android:radius="5dp"/> </shape> </item> <item android:right="1dp" android:left="1dp" android:bottom="2dp"> <shape android:shape="rectangle"> <solid android:color="@android:color/white"/> <corners android:radius="5dp"/> </shape> </item> </layer-list>
Then add the layer-list as background in your LinearLayout.
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/background_with_shadow"/>
You can also read: http://odedhb.blogspot.com/2013/05/android-layout-shadow-without-9-patch.html
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dp" android:background="#CC55CC"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TableLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:stretchColumns="0"> <TableRow> <LinearLayout android:id="@+id/content" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#FFFFFF" android:text="@string/hello" /> </LinearLayout> <View android:layout_width="5dp" android:layout_height="fill_parent" android:layout_marginTop="5dp" android:background="#55000000"/> </TableRow> </TableLayout> <View android:layout_width="fill_parent" android:layout_height="5dp" android:layout_marginLeft="5dp" android:background="#55000000"/> </LinearLayout> </FrameLayout>
I'm using Android Studio 0.8.6 and I couldn't find:
android:background="@drawable/abc_menu_dropdown_panel_holo_light"
so I found this instead:
android:background="@android:drawable/dialog_holo_light_frame"
and it looks like this:
If you're interested in clean Material Design effect, read some documentation like below:
Upvotes: 10
Reputation: 1324
Top only Shadow:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape>
<padding
android:top="@dimen/_2sdp" />
<solid android:color="@color/red" />
<corners android:radius="@dimen/_8sdp" />
</shape>
</item>
<!-- Background -->
<item>
<shape>
<solid android:color="@color/white" />
<corners android:radius="@dimen/_8sdp" />
</shape>
</item>
if you want shadow to appear in other areas add padding bottom
, right
, left
Result:
Upvotes: 3
Reputation: 1359
On hack I found for this is to wrap your view in a parent and use rotate. E.g. if you have a cardview and are adding elevation to it, you can put two rotates like this to achieve a shadow above instead of below:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingBottom="10dp"
android:rotation="180">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:rotation="180"
app:cardElevation="8dp">
<!--Card view content-->
</android.support.v7.widget.CardView>
</RelativeLayout>
This gives something like the attached screenshot.
There's still a problem with this - this requires the paddingBottom to be set on the parent layout which means it'll be obvious that any scrollable sibling above the layout isn't going below it.
So even in today's age of elevation and outline provider, it's better to add a translucent view instead. :(
Upvotes: 5