在 Android 上为自定义形状添加阴影

Posted

技术标签:

【中文标题】在 Android 上为自定义形状添加阴影【英文标题】:Add shadow to custom shape on Android 【发布时间】:2011-03-04 18:40:05 【问题描述】:

是否可以在 android 中为自定义形状添加阴影?浏览文档后,我只看到了一种应用文本阴影的方法。

我试过这个没有运气:

<?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>

【问题讨论】:

【参考方案1】:

找了好久终于找到了

<?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>

【讨论】:

你在哪里配置&lt;!-- Bottom 2dp Shadow --&gt;我在你的代码中没有看到任何2...???【参考方案2】:

这就是我的做法:

一键状态代码如下:

<?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>

那么你应该有一个带有不同版本按钮的选择器,例如:

<?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>

希望这可以帮助你..祝你好运

【讨论】:

【参考方案3】:

这是我的投影版本。我打算在形状周围画一个朦胧的阴影,并使用this answer by Joakim Lundborg 作为我的起点。我更改的是为所有阴影项添加角,并为每个后续阴影项增加角的半径。所以这里是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>

【讨论】:

工作正常.. 谢谢(y)【参考方案4】:

我觉得这个方法效果很好:

<!-- 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:/>
        <solid android:color="#FFF" />
        <corners android:radius="2dp" />

    </shape>

</item>

【讨论】:

【参考方案5】:

以下内容对我有用:只需另存为 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>

【讨论】:

【参考方案6】:

我建议对 Bruce 的解决方案进行小幅改进,即防止在彼此之上过度绘制相同的形状,并简单地使用笔触而不是实体。 它看起来像这样:

<?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:  />
            <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: />
            <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: />
            <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: />
            <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: />
            <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: />
            <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: />
            <corners android:radius="3dp" />
        </shape>
    </item>

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

最后,我想为那些想要在特定方向上的阴影的人指出,你所要做的就是将顶部、底部、左侧或右侧设置为 0dp(实线)或 -1dp(无)

【讨论】:

【参考方案7】:

Material Design 提供的旧问题,但 Elevation 现在可为任何视图提供阴影。

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

请参阅https://developer.android.com/training/material/shadows-clipping.html 上的文档

【讨论】:

如果您有几个 UI 小部件,它们应该在最外面的形状周围出现一个阴影,该怎么办?我尝试向外部添加高度,但内部则隐藏在外部之后。所以我尝试为两者添加高程,但看起来内部的在外部的顶部有一个阴影,就像印加金字塔一样。 我最终通过使用单个 ImageButton 而不是 ImageView 加上 Button' because it allows a ImageButton 来处理融合,同时允许 android:backgroundandroid:src。因此,我能够只指定一次android:elevation,并避免了我在上一条评论中描述的“印加金字塔效应”。【参考方案8】:

如果您不介意使用 Canvas API 进行一些自定义绘图,请查看有关 drop shadows 的答案。这是一个follow-up 问题,可以解决原始问题。

【讨论】:

【参考方案9】:

  <?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:
            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>

【讨论】:

【参考方案10】:

这个问题可能很老了,但对于任何想要一种简单的方法来实现复杂阴影效果的人来说,请在这里查看我的库https://github.com/BluRe-CN/ComplexView

使用该库,您可以更改阴影颜色、调整边缘等等。这是一个实现您所寻求的示例。

<com.blure.complexview.ComplexView
        android:layout_
        android:layout_
        app:radius="10dp"
        app:shadow="true"
        app:shadowSpread="2">

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

要更改阴影颜色,请使用 app:shadowColor="your color code"。

【讨论】:

【参考方案11】:

9个补丁,轻松实现漂亮的阴影 尤其是这个很棒的工具 -

Android 9-patch shadow generator

PS:如果项目无法编译,您需要在 android studio 编辑器中移动黑线一点

【讨论】:

【参考方案12】:

我认为这个阴影值在大多数情况下都很好:

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

【讨论】:

【参考方案13】:

如果您需要直线阴影(如工具栏底部),您也可以使用渐变 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>

希望对某人有所帮助

【讨论】:

【参考方案14】:

如果您在自定义背景可绘制对象上设置 &lt;solid&gt;&lt;stroke&gt;,由于某些原因,阴影将不起作用。创建一个 &lt;layer-list&gt; 具有单独的填充和边框图层可以解决此问题:

<?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:/>
            <corners android:radius="@dimen/card_corner_radius" />
        </shape>
    </item>
</layer-list>

【讨论】:

【参考方案15】:

只需将海拔设置为 10 左右。 https://developer.android.com/training/material/shadows-clipping

【讨论】:

以上是关于在 Android 上为自定义形状添加阴影的主要内容,如果未能解决你的问题,请参考以下文章

如何将 MKMapView(或任何 UIView)裁剪为自定义形状?

Android Gradle 插件自定义 Gradle 任务 ⑤ ( 为自定义 Gradle 任务添加依赖任务 | Gradle 任务依赖执行顺序控制 )

Android Gradle 插件自定义 Gradle 任务 ⑤ ( 为自定义 Gradle 任务添加依赖任务 | Gradle 任务依赖执行顺序控制 )

Android自定义边框加阴影

如何在android的linearlayout中删除阴影?

将地图标记设置为自定义颜色 Android