开发者

Add shadow to custom shape on Android

Is it possible to add a d开发者_高级运维rop shadow to a custom shape in Android? After looking through the documentation, I only see a way to apply a text shadow.

I've tried this with no luck:

<?xml version="1.0" encoding="UTF-8"?> 
   <shape xmlns:android="http://schemas.android.com/apk/res/android" 
   android:shape="rectangle"> 
     <solid android:color="#90ffffff"/>
       <corners android:radius="12dp" />
     <item name="android:shadowColor">#000000</item> 
     <item name="android:shadowRadius">5</item> 
     <item name="android:shadowDy">3</item> 
   </shape>


After Lots of search finally I got this

Add shadow to custom shape on Android

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<!-- Bottom 2dp Shadow -->
<item>
    <shape  android:shape="rectangle">

        <solid android:color="#d8d8d8" />
        <corners android:radius="7dp" />

    </shape>
</item>

<!-- White Top color -->
<item android:bottom="3px">

    <shape  android:shape="rectangle">

    <solid android:color="#FFFFFF" />
    <corners android:radius="7dp" />


    </shape>

</item>


</layer-list>


This is how I do it:

Add shadow to custom shape on Android

Code bellow for one button STATE:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- "background shadow" -->
    <item>
        <shape android:shape="rectangle" >
            <solid android:color="#000000" />

            <corners android:radius="15dp" />
        </shape>
    </item>
    <!-- background color -->
    <item
        android:bottom="3px"
        android:left="3px"
        android:right="3px"
        android:top="3px">
        <shape android:shape="rectangle" >
            <solid android:color="#cc2b2b" />


            <corners android:radius="8dp" />
        </shape>
    </item>
    <!-- over left shadow -->
    <item>
        <shape android:shape="rectangle" >
            <gradient
                android:angle="180"
                android:centerColor="#00FF0000"
                android:centerX="0.9"
                android:endColor="#99000000"
                android:startColor="#00FF0000" />

            <corners android:radius="8dp" />
        </shape>
    </item>
    <!-- over right shadow -->
    <item>
        <shape android:shape="rectangle" >
            <gradient
                android:angle="360"
                android:centerColor="#00FF0000"
                android:centerX="0.9"
                android:endColor="#99000000"
                android:startColor="#00FF0000" />

            <corners android:radius="8dp" />
        </shape>
    </item>
    <!-- over top shadow -->
    <item>
        <shape android:shape="rectangle" >
            <gradient
                android:angle="-90"
                android:centerColor="#00FF0000"
                android:centerY="0.9"
                android:endColor="#00FF0000"
                android:startColor="#99000000"
                android:type="linear" />

            <corners android:radius="8dp" />
        </shape>
    </item>
    <!-- over bottom shadow -->
    <item>
        <shape android:shape="rectangle" >
            <gradient
                android:angle="90"
                android:centerColor="#00FF0000"
                android:centerY="0.9"
                android:endColor="#00FF0000"
                android:startColor="#99000000"
                android:type="linear" />

            <corners android:radius="8dp" />
        </shape>
    </item>
</layer-list>

Then you should have a selector with diferent versions of the button, something like:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/ic_button_red_pressed" android:state_pressed="true"/> <!-- pressed -->
    <item android:drawable="@drawable/ic_button_red_selected" android:state_focused="true"/> <!-- focused -->
    <item android:drawable="@drawable/ic_button_red_selected" android:state_selected="true"/> <!-- selected -->
    <item android:drawable="@drawable/ic_button_red_default"/> <!-- default -->

</selector>

hope this can help you..good luck


This is my version of a drop shadow. I was going for a hazy shadow all around the shape and used this answer by Joakim Lundborg as my starting point. What I changed is to add corners to all the shadow items and to increase the radius of the corner for each subsequent shadow item. So here is the xml:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Drop Shadow Stack -->
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <solid android:color="#02000000" />
            <corners android:radius="8dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <solid android:color="#05000000" />
            <corners android:radius="7dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <solid android:color="#10000000" />
            <corners android:radius="6dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <solid android:color="#15000000" />
            <corners android:radius="5dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <solid android:color="#20000000" />
            <corners android:radius="4dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <solid android:color="#25000000" />
            <corners android:radius="3dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <solid android:color="#30000000" />
            <corners android:radius="3dp" />
        </shape>
    </item>

    <!-- Background -->
    <item>
    <shape>
            <solid android:color="#0099CC" />
        <corners android:radius="3dp" />
    </shape>
   </item>
</layer-list>


I think this method produces very good results:

<!-- Drop Shadow Stack -->
<item>
    <shape>
        <padding
                android:top="1dp"
                android:right="1dp"
                android:bottom="1dp"
                android:left="1dp"/>
        <solid android:color="#00CCCCCC"/>
    </shape>
</item>
<item>
    <shape>
        <padding
                android:top="1dp"
                android:right="1dp"
                android:bottom="1dp"
                android:left="1dp"/>
        <solid android:color="#10CCCCCC"/>
    </shape>
</item>
<item>
    <shape>
        <padding
                android:top="1dp"
                android:right="1dp"
                android:bottom="1dp"
                android:left="1dp"/>
        <solid android:color="#20CCCCCC"/>
    </shape>
</item>
<item>
    <shape>
        <padding
                android:top="1dp"
                android:right="1dp"
                android:bottom="1dp"
                android:left="1dp"/>
        <solid android:color="#30CCCCCC"/>
    </shape>
</item>
<item>
    <shape>
        <padding
                android:top="1dp"
                android:right="1dp"
                android:bottom="1dp"
                android:left="1dp"/>
        <solid android:color="#50CCCCCC"/>
    </shape>
</item>

<item>

    <shape android:shape="rectangle">
        <stroke android:color="#CCC" android:width="1dp"/>
        <solid android:color="#FFF" />
        <corners android:radius="2dp" />

    </shape>

</item>


The following worked for me: Just save as custom_shape.xml.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <!-- "shadow" -->
    <item>
        <shape android:shape="rectangle" >
           <solid android:color="#000000"/>
           <corners android:radius="12dp" />
        </shape>
    </item>


    <item android:bottom="3px">
        <shape android:shape="rectangle"> 
            <solid android:color="#90ffffff"/>
            <corners android:radius="12dp" />
         </shape>
    </item>

</layer-list>


I would suggest a small improvement to Bruce's solution which is to prevent overdrawing the same shape on top of each other and to simply use stroke instead of solid. It would look like this:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Drop Shadow Stack -->
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <stroke android:color="#02000000" android:width="1dp"  />
            <corners android:radius="8dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <stroke android:color="#05000000" android:width="1dp" />
            <corners android:radius="7dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <stroke android:color="#10000000" android:width="1dp" />
            <corners android:radius="6dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <stroke android:color="#15000000" android:width="1dp" />
            <corners android:radius="5dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <stroke android:color="#20000000" android:width="1dp" />
            <corners android:radius="4dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <stroke android:color="#25000000" android:width="1dp" />
            <corners android:radius="3dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <stroke android:color="#30000000" android:width="1dp" />
            <corners android:radius="3dp" />
        </shape>
    </item>

    <!-- Background -->
    <item>
        <shape>
            <solid android:color="#FFF" />
            <corners android:radius="3dp" />
        </shape>
    </item>
</layer-list>

Add shadow to custom shape on Android

Lastly I wanted to point out for people who would like a shadow in a specific direction that all you have to do is set the top, bottom, left or right to 0dp (for a solid line) or -1dp (for nothing)


Old question, but Elevation, available with Material Design now provides a shadow to any views.

<TextView
android:id="@+id/myview"
...
android:elevation="2dp"
android:background="@drawable/myrect" />

See the docs at https://developer.android.com/training/material/shadows-clipping.html


If you don't mind doing some custom drawing with the Canvas API, check out this answer about drop shadows. Here's a follow-up question to that one which fixes a problem in the original.


Add shadow to custom shape on Android

  <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android" >

        <solid android:color="@android:color/white" >
        </solid>

        <stroke
            android:width="1dp"
            android:color="@color/LightGrey" >
        </stroke>

        <padding
            android:bottom="5dp"
            android:left="2dp"
            android:right="2dp"
            android:top="5dp" >
        </padding>

        <corners
            android:bottomLeftRadius="20dp"
            android:bottomRightRadius="20dp"
            android:radius="12dp"
            android:topLeftRadius="20dp"
            android:topRightRadius="20dp" />

        <gradient
            android:angle="90"
            android:centerColor="@android:color/white"
            android:centerY="0.2"
            android:endColor="#99e0e0e0"
            android:startColor="@android:color/white"
            android:type="linear" />

    </shape>


This question may be old, but for anybody in future that wants a simple way to achieve complex shadow effects check out my library here https://github.com/BluRe-CN/ComplexView

Using the library, you can change shadow colors, tweak edges and so much more. Here's an example to achieve what you seek for.

<com.blure.complexview.ComplexView
        android:layout_width="400dp"
        android:layout_height="600dp"
        app:radius="10dp"
        app:shadow="true"
        app:shadowSpread="2">

        <com.blure.complexview.ComplexView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:color="#fdfcfc"
            app:radius="10dp" />
    </com.blure.complexview.ComplexView>

To change the shadow color, use app:shadowColor="your color code".


9 patch to the rescue, nice shadow could be achieved easily especially with this awesome tool -

Android 9-patch shadow generator

PS: if project won't be able to compile you will need to move black lines in android studio editor a little bit


I think this drop shadow value is good for most cases:

<solid android:color="#20000000" />


if you need a straight line shadow (like in bottom of toolbar) you can also use gradient xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
        android:type="linear"
        android:angle="-90"
        android:startColor="#19000000" <!-- black transparent -->
        android:endColor="#00000000" /> <!-- full transparent -->
</shape>

hope this help some one


For some reason shadows don't work if you set <solid> AND <stroke> on your custom background drawable. Creating a <layer-list> with separate layers for fill and borders fixes the issue:

<?xml version="1.0" encoding="utf-8"?>
<!-- Separate layers for solid and stroke, because no shadows get drawn otherwise (using elevation) -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/card_default" />
            <corners android:radius="@dimen/card_corner_radius" />
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle">
            <stroke android:color="@color/card_border" android:width="@dimen/card_border_width"/>
            <corners android:radius="@dimen/card_corner_radius" />
        </shape>
    </item>
</layer-list>


            <?xml version="1.0" encoding="utf-8"?>
            <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
                <item
                    android:bottom="3dp"
                    android:left="5dp"
                    android:right="5dp"
                    android:top="5dp">
                    <shape android:shape="rectangle">
                        <gradient
                            android:startColor="@color/white"
                            android:endColor="@color/gray"
                            android:angle="270"
                            android:dither="false"/>
                        <corners android:radius="@dimen/_20dp" />
                    </shape>
                </item>
                <item
                    android:bottom="6dp"
                    android:left="6dp"
                    android:right="6dp"
                    android:top="6dp">
                    <shape android:shape="rectangle">
                        <solid android:color="@color/orange" />
                        <corners android:radius="@dimen/_20dp" />
                    </shape>
                </item>
            </layer-list>


Just set elevation to something like 10. https://developer.android.com/training/material/shadows-clipping

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜