Android阴影背景的实现

作者: 微风吹皱一池春水 | 来源:发表于2019-05-11 20:51 被阅读0次

一、需求来源:

设计师要求还原设计的阴影,下面是sketch原型参数:

圆角:8px

外阴影:                    
Offset:     0px     1px                         
             X       Y              

Effect:     10px    0px                 
            Blur    Spread                  

颜色:      #135B90D0                       

二、Android本身控件自带阴影效果无法还原

Google的Material Design中对于阴影的定义是:海拔高度是相对深度或距离,是两个表面在 Z 轴上的距离。

实现方式:

  • 第一种方式:elevation属性
    View的大小位置都是通过x,y确定的,而现在有了z轴的概念,而这个z值就是View的高度(elevation),而高度决定了阴影(shadow)的大小。

  • 第二种方式:CardView自带属性

card_view:cardElevation 阴影的大小
card_view:cardMaxElevation 阴影最大高度
card_view:cardBackgroundColor 卡片的背景色
card_view:cardCornerRadius 卡片的圆角大小
card_view:contentPadding 卡片内容于边距的间隔
  • 第三种方式:
    设置边框为shape,通过layer-list实现层次感
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
    <shape android:shape="oval">
        <padding
            android:bottom="2dp"
            android:left="2dp"
            android:right="2dp"
            android:top="2dp" />
        <solid android:color="#0DF3F3F3" />
        <corners android:radius="8dp" />
    </shape>
</item>
    <item>
        <shape
            android:layout_width="wrap_content"
            android:shape="oval">
            <padding
                android:bottom="2dp"
                android:left="2dp"
                android:right="2dp"
                android:top="2dp" />
            <solid android:color="#10F3F3F3" />
            <corners android:radius="8dp" />
        </shape>
    </item>
<item>
    <shape android:shape="oval">
        <padding
            android:bottom="2dp"
            android:left="2dp"
            android:right="2dp"
            android:top="2dp" />
        <solid android:color="#15F3F3F3" />
        <corners android:radius="8dp" />
    </shape>
</item>
<item>
    <shape android:shape="oval">
        <padding
            android:bottom="2dp"
            android:left="2dp"
            android:right="2dp"
            android:top="2dp" />
        <solid android:color="#20F3F3F3" />
        <corners android:radius="8dp" />
    </shape>
</item>
<item>
    <shape android:shape="oval">
        <padding
            android:bottom="2dp"
            android:left="2dp"
            android:right="2dp"
            android:top="2dp" />
        <solid android:color="#25F3F3F3" />
        <corners android:radius="8dp" />
    </shape>
</item>
<item>
    <shape android:shape="oval">
        <solid android:color="#FFFFFF" />
    </shape>
</item>
</layer-list>

三、使用Android画笔Paint来实现

  • 第四种方式(属性一一对应设计稿):
/**
 * 使用圆角时,应设置圆角相同的background
 */

public class ShadowRelativeLayout extends RelativeLayout {
    /**
     * 阴影的颜色
     */
    private int shadowColor = Color.argb(90, 0, 0, 0);
    /**
     * 高斯模糊的模糊半径,值越大越模糊,越小越清晰,
     */
    private float shadowBlur = 30;
    /**
     * 阴影的圆角
     */
    private float shadowRadius = 0;

    /**
     * 阴影的偏移
     */
    private float shadowDx = 0;
    private float shadowDy = 0;

    public ShadowRelativeLayout(@NonNull Context context) {
        this(context, null);
    }

    public ShadowRelativeLayout(@NonNull Context context,
                                @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ShadowRelativeLayout(@NonNull Context context, @Nullable AttributeSet attrs,
                                int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        dealAttrs(context, attrs);
        setPaint();
    }

    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    @Override
    public void draw(Canvas canvas) {
        setInsetBackground();
        canvas.drawRoundRect(getRectF(), shadowRadius, shadowRadius, mPaint);
        super.draw(canvas);
    }

    private boolean setInsetBackground() {
        Drawable background = getBackground();
        if (background == null || background instanceof InsetDrawable) {
            return false;
        }
        InsetDrawable drawable =
                new InsetDrawable(background, getPaddingLeft(), getPaddingTop(),
                        getPaddingRight(), getPaddingBottom());
        setBackground(drawable);
        return true;
    }

    private RectF getRectF() {
        return new RectF(getPaddingLeft() + shadowDx, getPaddingTop() + shadowDy,
                getWidth() - getPaddingRight() + shadowDx,
                getHeight() - getPaddingBottom() + shadowDy);
    }

    private void dealAttrs(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ShadowRelativeLayout);
        if (typedArray != null) {
            shadowColor = typedArray.getColor(R.styleable.ShadowRelativeLayout_shadow_color, shadowColor);
            shadowRadius =
                    typedArray.getDimension(R.styleable.ShadowRelativeLayout_shadow_radius, shadowRadius);
            shadowBlur =
                    typedArray.getDimension(R.styleable.ShadowRelativeLayout_shadow_blur, shadowBlur);
            shadowDx = typedArray.getDimension(R.styleable.ShadowRelativeLayout_shadow_dx, shadowDx);
            shadowDy = typedArray.getDimension(R.styleable.ShadowRelativeLayout_shadow_dy, shadowDy);
            typedArray.recycle();
        }
    }

    private void setPaint() {
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);  // 关闭硬件加速,阴影才会绘制
        // todo 从AttributeSet获取设置的值
        mPaint.setAntiAlias(true);
        mPaint.setColor(shadowColor);
        mPaint.setMaskFilter(new BlurMaskFilter(shadowBlur, BlurMaskFilter.Blur.NORMAL));
    }

    @Override
    public boolean isOpaque() { //纯色或图片做背景时,draw之前会有黑底色,
        return false;
    }
}

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ShadowRelativeLayout">
        <attr format="color" name="shadow_color"/>
        <attr format="dimension" name="shadow_radius"/>
        <attr format="dimension" name="shadow_blur"/>
        <attr format="dimension" name="shadow_dx"/>
        <attr format="dimension" name="shadow_dy"/>
    </declare-styleable>
</resources>

使用范例(属性完美映射设计稿):

<ShadowRelativeLayout
    android:layout_width="180dp"
    android:layout_height="100dp"
    android:background="@drawable/shape_round_white_dp8"
    android:padding="10dp"
    bind:shadow_blur="10dp"
    bind:shadow_color="#135B90D0"
    bind:shadow_dx="0dp"
    bind:shadow_dy="1dp"
    bind:shadow_radius="8dp">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_gravity="center"
        android:scaleType="center"
        android:src="@drawable/light" />
</ShadowRelativeLayout>

相关文章

  • Android阴影背景的实现

    一、需求来源: 设计师要求还原设计的阴影,下面是sketch原型参数: 二、Android本身控件自带阴影效果无法...

  • 阴影背景实现

    1.android:background="@android:drawable/dialog_holo_light...

  • Android 背景阴影效果

    在drawable文件夹下建立一个shadow.xml文件,内容如下: 在你的button里面,设置背景如下:

  • Android打造带阴影的气泡

    前言 在做Android项目的时候,我们的射鸡师常常会使用阴影,Android实现阴影目前主流有以下几种方式:1)...

  • 阴影的实现多种方案研究

    要实现阴影,解决方法有很多,有直接当前控件携带阴影 移动自己的背景图层,或者是让父容器进行背景图层绘制阴影,

  • 自定义通用dialog 背景有阴影

    学习文章 android自定义Dialog弹框和背景阴影显示 style layout 颜色 圆角 Android...

  • Android 设置View的阴影背景

    公司的项目需要实现一个View的阴影渐变背景效果,然后展示的内容是一个九宫格形式,如下图: 开始想直接使用shap...

  • Android阴影效果与CardView版本适配的细节问题

    记录一下使用cardView来实现阴影效果时碰到的版本适配的解决方案。 一、背景 在API 21以前想要实现阴影效...

  • Android 实现阴影效果

    第一层是阴影图层 居上 和左3dp,第二层是 背景图层 居下和右3dp这样右和下面阴影边就露出来了 当然我们也可以...

  • Android阴影简单实现

    :) 阴影绘制需要的知识点 硬件加速 Paint对象的setShadowLayer方法 android硬件加速 A...

网友评论

    本文标题:Android阴影背景的实现

    本文链接:https://www.haomeiwen.com/subject/kyyfaqtx.html