如何在安卓中为一个View设置阴影?

26

我想知道如何在Android中为任何一般的View添加阴影层。例如:假设我有一个布局xml,显示如下内容...

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout  
    android:layout_height="wrap_content"  
    android:layout_width="wrap_content"  
    <Button....  
    ...  
</LinearLayout>  

现在当它被显示时,我希望它周围有一个阴影。


类似的问题在这里 https://dev59.com/sK_la4cB1Zd3GeqPq06k - 如何为矢量图形添加轮廓。 - Mayank Kumar Chaudhari
7个回答

38

创建阴影的最佳方法是使用一个9patch图像作为视图(或包含视图的ViewGroup)的背景。

第一步是创建一个带有阴影的PNG图像。我用Photoshop创建了这样一张图片,非常简单:

  • 使用Photoshop创建一个新图像。
  • 添加一个层并创建一个4x4的黑色正方形。
  • 通过选择图层资源管理器中的图层,然后单击题为fx和选择投影的按钮,在该层上创建一个阴影。
  • 将图像导出为png格式。

下一步是从此图像创建9-patch可绘制对象:

  • android-sdk/tools打开draw9patch
  • draw9patch中打开图像。
  • 在正方形的四个边上创建4条黑线,如下所示,然后将图像另存为shadow.9.png

现在,您可以将此阴影添加为要添加阴影的视图的背景。将shadow.9.png添加到res/drawables,然后将其添加为背景即可:

<LinearLayout
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:background="@drawable/shadow"
  android:paddingBottom="5px"
  android:paddingLeft="6px"
  android:paddingRight="5px"
  android:paddingTop="5px"
>

我最近写了一篇博客文章,详细解释了这个过程,并包括我用于创建阴影的9patch图像。


1
这比被接受的答案要好得多。此外,博客链接已失效。 - Isaac Zais
1
@ranjith 从终端运行SDK sdk/tools目录中的draw9patch命令,启动Draw 9-patch工具。 - Sapan Diwakar
1
有一个工具可以在线创建9宫格图片:http://inloop.github.io/shadow4android/ - Rukmal Dias

13

假设您使用线性布局(我考虑了垂直线性布局)..并且线性布局下方刚好有一个视图。现在为此视图提供起始颜色和结束颜色..

我也想要这个东西,对我来说很有效。如果您需要更好的效果,则可以尝试调整起始和结束颜色。

activity_main

<?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:orientation="vertical" >

    <LinearLayout
        android:id="@+id/vertical"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:background="@drawable/layout_back_bgn"
        android:orientation="vertical" >
    </LinearLayout>

    <View
        android:layout_below="@+id/vertical"
        android:layout_width="match_parent"
        android:layout_height="10dp"
        android:background="@drawable/shadow"
        >
    </View>


</LinearLayout>

layout_back_bgn.xml

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >

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

</shape>

shadow.xml

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android"  android:shape="rectangle">    
    <gradient
        android:startColor="#4D4D4D"
        android:endColor="#E6E6E6"
        android:angle="270"
        >
    </gradient>
</shape>

我尝试使用上面的代码上传一张图片,但因为我的声誉值不够,stackoverflow不允许我这样做...非常抱歉。


就我所知,我认为你的声誉非常好。感谢你的回答。 - sudocoder

10

您可以使用自API级别21以来提供的高度(elevation)属性。

视图的高度(elevation)由其Z属性表示,决定了其阴影的视觉外观:具有更高Z值的视图投射出更大、更柔和的阴影。具有更高Z值的视图遮盖具有较低Z值的视图;但是,视图的Z值不会影响其大小。要设置视图的高度,请:

在布局定义中使用

android:elevation

属性。要在活动的代码中设置视图的高程,请使用

View.setElevation()
< p > 方法。 < /p >< p >来源


4
只有当您的目标是 API 21(棒棒糖)及以上版本时,此解决方案才有效。 - Corentin Bruneau

5
这是我简单的解决方案...这是根据此处的解决方案进行修改。
我不喜欢角落看起来的样子,所以我把它们都变淡了...
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!--Layer 0-->
<!--Layer 1-->
<!--Layer 2-->
<!--Layer 3-->
<!--Layer 4 (content background)-->

<!-- dropshadow -->
<item>
    <shape>
        <gradient 
            android:startColor="@color/white"
            android:endColor="@color/white"
            android:centerColor="#10CCCCCC"
            android:angle="180"/>
        <padding android:top="0dp" android:right="0dp" android:bottom="2dp" android:left="0dp" />
    </shape>
</item>

<item>
    <shape>
        <gradient 
            android:startColor="@color/white"
            android:endColor="@color/white"
            android:centerColor="#20CCCCCC"
            android:angle="180"/>
        <padding android:top="0dp" android:right="0dp" android:bottom="2dp" android:left="0dp" />
    </shape>
</item>

<item>
    <shape>
        <gradient 
            android:startColor="@color/white"
            android:endColor="@color/white"
            android:centerColor="#30CCCCCC"
            android:angle="180"/>

        <padding android:top="0dp" android:right="0dp" android:bottom="2dp" android:left="0dp" />
    </shape>
</item>

<item>
    <shape>
        <gradient 
            android:startColor="@color/white"
            android:endColor="@color/white"
            android:centerColor="#40CCCCCC"
            android:angle="180"/>
        <padding android:top="0dp" android:right="0dp" android:bottom="2dp" android:left="0dp" />
    </shape>
</item>

<item>
    <shape>
        <gradient 
            android:startColor="@color/white"
            android:endColor="@color/white"
            android:centerColor="#50CCCCCC"
            android:angle="180"/>
        <padding android:top="0dp" android:right="0dp" android:bottom="2dp" android:left="0dp" />
    </shape>
</item>

<!-- content background -->
<item>
    <shape>
        <solid android:color="@color/PostIt_yellow" />
    </shape>
</item>


2
在屏幕上看起来非常糟糕!而且添加太多图层可能会导致渲染问题。 - sud007

3
有一个简单的技巧,使用两个视图来形成阴影。
<?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>

希望这可以帮到您。

6
最好使用渐变来改变颜色。 - Amokrane Chentir
1
使用9patch可绘制背景比较简单,布局也更加清晰。 - Lubos Horacek
感谢@praveenb,不过我认为9patch可拉伸图片背景是最好的解决方案。 - Fede
2
这不是在XML中正确的做法。它会增加布局的深度,可能会导致低端手机甚至高端手机的UI渲染变慢。 正确的方法始终是使用9patch图像。建议制作一个更清洁和性能敏锐的UI,而不仅仅是为了好看。 - sud007

0
在res/drawable文件夹中创建card_background.xml文件,并使用以下代码:
<?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="#BDBDBD"/>
        <corners android:radius="5dp"/>
    </shape>
</item>

<item
    android:left="0dp"
    android:right="0dp"
    android:top="0dp"
    android:bottom="2dp">
    <shape android:shape="rectangle">
        <solid android:color="#ffffff"/>
        <corners android:radius="5dp"/>
    </shape>
</item>
</layer-list>

然后将以下代码添加到您想要使用卡片布局的元素中

android:background="@drawable/card_background"

以下代码定义了卡片阴影的颜色

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

-1

enter image description here

</LinearLayout>
            <View
                android:layout_width="match_parent"
                android:layout_height="2dp"
                android:background="@color/dropShadow" />

使用LinearLayout正下方

另一种方法

enter image description here

在/drawable文件夹中创建"rounded_corner_bg.xml"。
<?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="@color/primaryColor" />

        <corners android:radius="4dp" />
    </shape>
</item>

<item
    android:bottom="2dp"
    android:left="0dp"
    android:right="0dp"
    android:top="0dp">
    <shape android:shape="rectangle">
        <solid android:color="#F7F7F7" />

        <corners android:radius="4dp" />
    </shape>
</item>

</layer-list>

使用此布局 android:background="@drawable/rounded_corner_bg"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接