关于 Android 阴影,大家肯定不陌生的。但是Android 中到底有多少种方式可以实现阴影效果以及各种方式之间有什么区别和优缺点,这就是我想总结的。下面我们一个一个来说:

一、各种实现阴影的方式

  1. Android 在 API 21(5.0)添加了 elevation,可以很方便的在 View 上实现阴影。但是这个只在 >= API21 的手机上可以看到阴影效果,低于这个版本的就没有阴影效果。目前市场上应用还是需要适配至 API15 的,所以需要慎重使用。

  2. CardView 也可以实现阴影效果,项目中一般都是使用这种方式实现卡片式的效果并带有阴影。使用 CardView 确实很不错,但是它在使用的时候也是需要有注意的地方:

    (1) CardView 实现阴影效果的布局,在 >= API 21 的版本上和 < 21 的版本上,如果不在代码上做好控制,他们的显示差异还是很大的。至于如何进行适配,可以自行查找。有图有真相:大小呈现差异,阴影有差异:测试机型都一致,只有Android 版本差异,对于左下角的 cardBackgroundcolor 透明也是有差异的。左侧为 API 15  、 右侧为 API 22

    

Android layer list阴影效果 android view阴影_shape

    

Android layer list阴影效果 android view阴影_shape_02

阴影方向不一致,这一点造成了我在开发中的一个 BUG,很头痛啊,这也是一个 BUG,后面会有解决这个 。有图有真相:

Android layer list阴影效果 android view阴影_阴影效果_03

    (3)如果有对阴影颜色有要求的需求, CardView 不好意思,臣妾做不到啊。哈哈,CardView 黑的差不多了。

  3. Shape 来实现阴影。通过这种方式来实现阴影,由于shape是作为背景来使用的,阴影的存在有可能使内容显示在阴影部分即阴影也占位哈。硬伤啊,当然你可以手动设置 margin 或者 padding 值控制内容的显示位置,当然要是 dp 适配的哈。我们来看一下 shape 如何实现阴影:

Android layer list阴影效果 android view阴影_阴影_04

Android layer list阴影效果 android view阴影_shadow_05

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

    <!--边-->
    <item>
            <shape android:shape="rectangle">
            <padding
                android:bottom="2px"
                android:left="1px"
                android:right="2px"
                android:top="1px" />

            <solid android:color="#00CCCCCC" />

            <corners android:radius="5dp" />
        </shape>
    </item>
    <item>
            <shape android:shape="rectangle">
            <padding
                android:bottom="2px"
                android:left="1px"
                android:right="2px"
                android:top="1px" />

            <solid android:color="#10CCCCCC" />

            <corners android:radius="5dp" />
        </shape>
    </item>
    <item>
            <shape android:shape="rectangle">
            <padding
                android:bottom="2px"
                android:left="1px"
                android:right="2px"
                android:top="1px" />

            <solid android:color="#20CCCCCC" />

            <corners android:radius="5dp" />
        </shape>
    </item>
    <item>
            <shape android:shape="rectangle">
            <padding
                android:bottom="2px"
                android:left="1px"
                android:right="2px"
                android:top="1px" />

            <solid android:color="#30CCCCCC" />

            <corners android:radius="5dp" />
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle">
            <padding
                android:bottom="2px"
                android:left="1px"
                android:right="2px"
                android:top="1px" />

            <solid android:color="#50CCCCCC" />
            <corners android:radius="5dp" />
        </shape>
    </item>

    <!--中心背景 -->
    <item>
        <shape
            android:shape="rectangle"
            android:useLevel="false">
            <!--实心 -->
            <solid android:color="@color/white_f2" />
            <corners android:radius="5dp" />
            <size android:width="32dp"
                android:height="32dp"/>

        </shape>
    </item>

</layer-list>

View Code

  效果图:

Android layer list阴影效果 android view阴影_阴影效果_06

  4. 通过 .9 图来制作阴影,这里通过一个很好的工具来制作哈:http://inloop.github.io/shadow4android/

    来看下界面:这种方式制作小的背景阴影很模糊,效果上比不过 shape。如果这个没太大关系,这种方式很方便,不用敲代码,哈哈。

  5.  用 SCardView 来实现阴影,使用方式和 CardView 一样,但是它是使用一套代码,显示不会有差异,而且可以通过设置光源的位置来控制阴影的方向以及阴影的颜色。来看下效果:

  

Android layer list阴影效果 android view阴影_android_07

  SCardView 如何在代码中使用: 添加依赖

compile 'io.github.meetsl:SCardView:1.0'

  XML 代码:

<com.meetsl.scardview.SCardView
        android:layout_width="@dimen/card_size"
        android:layout_height="@dimen/card_size"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_margin="20dp"
        app:cardBackgroundColor="#80B3FF"
        app:cardCornerRadius="5dp"
        app:cardElevation="@dimen/cardview_elevation"
        app:cardLightDirection="RT">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:padding="5dp"
            android:text="RT"
            android:textColor="@android:color/white"
            android:textSize="16sp" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:src="@mipmap/home_back" />
    </com.meetsl.scardview.SCardView>

二、总结各种方式

方式

是否有显示差异

是否可以控制阴影方向

是否可以设置阴影颜色

阴影是否占位

是否模糊

绘制效率

其他

elevation


不可控制

不可设置

不占位


高,通过 native 绘制

只在 API 21 生效

CardView


不可控制

不可设置

不占位


Api 21 上效率高,通过native 绘制

 

shape


可控

可设置

占位


一般

 

.9 图


可控,生效一次,更改需重新生成

 可设置,更改需重新生成

占位

模糊

慢(加载图片显示)

 

SCardView


可控

可设置

不占位


一般

 

阴影的各种绘制比较已经奉上,按照需求和方便程度,各取所需。就到这吧,周末愉快!