Android阴影最完整解析

Android系统带的阴影elevation

android:elevation="" 给控件添加一个浅灰色的阴影,控件必须设置背景android:background=""
而且控件要设置layout_margin阴影才会显示出来。
这个方式有个缺点,无法修改阴影颜色,无法设置阴影大小,只支持android5.0(21)及以上系统

Android系统带的阴影shadow

android:shadowColor="" 阴影颜色
android:shadowRadius="“阴影模糊度
android:shadowDy=”“阴影在y轴上的距离,正数阴影是右阴影,负数阴影是左阴影
android:shadowDx=”"阴影在x轴上的距离,正数阴影是下阴影,负数阴影是上阴影
缺点,只针对textView和button的文字有效

如何灵活的给控件设置阴影背景

思考一下,如果设置圆角背景,然后给控件设置阴影,其实阴影不带圆角,这时候很难看,也不是想要的效果,我们其实要的效果是对drawable进行处理,让背景本身具有阴影。所以我们需要重写drawable,实现一个带有阴影的drawable,我们查看Paint类,发现有个方法是

 public void setShadowLayer(float radius, float dx, float dy, int shadowColor) {
  mShadowLayerRadius = radius;
  mShadowLayerDx = dx;
  mShadowLayerDy = dy;
  mShadowLayerColor = shadowColor;
  nSetShadowLayer(mNativePaint, radius, dx, dy, shadowColor);
}
radius阴影模糊度
dx阴影在y轴上的距离,正数阴影是右阴影,负数阴影是左阴影
dy阴影在x轴上的距离,正数阴影是下阴影,负数阴影是上阴影
shadowColor阴影颜色

把paint设置阴影层之后,画出来的图形都带有阴影。

利用这个方法,我们可以画一个带阴影图形,下面我们画一个圆角矩形

    mShadowPaint = new Paint();
    mShadowPaint.setAntiAlias(true);
    mShadowPaint.setShadowLayer(shadowRadius, offsetX, offsetY, shadowColor);
    shadowRect = new RectF(left + distance, top + distance, right - distance,
     bottom - distance - mOffsetY);//只做了下阴影
    mShadowPaint.setColor(mBgColor[0]);
   canvas.drawRoundRect(shadowRect, mShapeRadius, mShapeRadius, mShadowPaint);

上面只是主要方法,并不完全
完整代码如下:

 /**
* 只写了下阴影,其他方向的阴影还需要写
*/
public class ShadowDrawable extends Drawable {

private Paint mShadowPaint;
private int mShapeRadius;
private int mOffsetY;
private int mBgColor[];
private RectF shadowRect;
private int distance = 10;//画shadowRect往回缩的距离,不然阴影画不全,如果控件要显示下阴影,宽度要比实际控件大20px,高度要不实际控件大20+mOffsetY

    private ShadowDrawable(int[] bgColor, int shapeRadius, int shadowColor, int shadowRadius, int offsetX, int offsetY) {
    this.mBgColor = bgColor;
    this.mShapeRadius = shapeRadius;
    this.mOffsetY = offsetY;

    mShadowPaint = new Paint();
    mShadowPaint.setAntiAlias(true);

    mShadowPaint.setShadowLayer(shadowRadius, offsetX, offsetY, shadowColor);
   }

   @Override
   public void setBounds(int left, int top, int right, int bottom) {
    super.setBounds(left, top, right, bottom);
    shadowRect = new RectF(left + distance, top + distance, right - distance,
            bottom - distance - mOffsetY);//只做了下阴影
   }

   @Override
   public void draw(@NonNull Canvas canvas) {
    if (mBgColor != null) {
        if (mBgColor.length == 1) {
            mShadowPaint.setColor(mBgColor[0]);//单色
        } else {
            mShadowPaint.setShader(new LinearGradient(shadowRect.left, 0, shadowRect.right,
                    shadowRect.height(), mBgColor, null, Shader.TileMode.CLAMP));//渐变色
        }
    }
    canvas.drawRoundRect(shadowRect, mShapeRadius, mShapeRadius, mShadowPaint);
   }

   @Override
   public void setAlpha(int alpha) {
    mShadowPaint.setAlpha(alpha);
   }

    @Override
   public void setColorFilter(@Nullable ColorFilter colorFilter) {
    mShadowPaint.setColorFilter(colorFilter);
   }

   @Override
   public int getOpacity() {
    return PixelFormat.TRANSLUCENT;
   }

   public static void setShadowDrawable(View view, Drawable drawable) {
    view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    ViewCompat.setBackground(view, drawable);
   }

   public static void setShadowDrawable(View view, int shapeRadius, int shadowColor, int shadowRadius, int offsetX, int offsetY) {
    ShadowDrawable drawable = new ShadowDrawable.Builder()
            .setShapeRadius(shapeRadius)
            .setShadowColor(shadowColor)
            .setShadowRadius(shadowRadius)
            .setOffsetX(offsetX)
            .setOffsetY(offsetY)
            .builder();
    view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    ViewCompat.setBackground(view, drawable);
   }

    public static void setShadowDrawable(View view, int bgColor, int shapeRadius, int shadowColor, int shadowRadius, int offsetX, int offsetY) {
    ShadowDrawable drawable = new ShadowDrawable.Builder()
            .setBgColor(bgColor)
            .setShapeRadius(shapeRadius)
            .setShadowColor(shadowColor)
            .setShadowRadius(shadowRadius)
            .setOffsetX(offsetX)
            .setOffsetY(offsetY)
            .builder();
    view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    ViewCompat.setBackground(view, drawable);
   }

   public static void setShadowDrawable(View view, int[] bgColor, int shapeRadius, int shadowColor, int shadowRadius, int offsetX, int offsetY) {
    ShadowDrawable drawable = new ShadowDrawable.Builder()
            .setBgColor(bgColor)
            .setShapeRadius(shapeRadius)
            .setShadowColor(shadowColor)
            .setShadowRadius(shadowRadius)
            .setOffsetX(offsetX)
            .setOffsetY(offsetY)
            .builder();
    view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    ViewCompat.setBackground(view, drawable);
   }

   public static class Builder {
    private int mShapeRadius;
    private int mShadowColor;
    private int mShadowRadius;
    private int mOffsetX = 0;
    private int mOffsetY = 0;
    private int[] mBgColor;

    public Builder() {
        mShapeRadius = 12;
        mShadowColor = Color.parseColor("#4d000000");
        mShadowRadius = 18;
        mOffsetX = 0;
        mOffsetY = 0;
        mBgColor = new int[1];
        mBgColor[0] = Color.TRANSPARENT;
    }


    public Builder setShapeRadius(int ShapeRadius) {
        this.mShapeRadius = ShapeRadius;
        return this;
    }

    public Builder setShadowColor(int shadowColor) {
        this.mShadowColor = shadowColor;
        return this;
    }

    public Builder setShadowRadius(int shadowRadius) {
        this.mShadowRadius = shadowRadius;
        return this;
    }

    public Builder setOffsetX(int OffsetX) {
        this.mOffsetX = OffsetX;
        return this;
    }

    public Builder setOffsetY(int OffsetY) {
        this.mOffsetY = OffsetY;
        return this;
    }

    public Builder setBgColor(int BgColor) {
        this.mBgColor[0] = BgColor;
        return this;
    }

    public Builder setBgColor(int[] BgColor) {
        this.mBgColor = BgColor;
        return this;
    }

    public ShadowDrawable builder() {
        return new ShadowDrawable(mBgColor, mShapeRadius, mShadowColor, mShadowRadius, mOffsetX, mOffsetY);
    }
   }
   }

在代码中我们只需要如下调用就可以实现圆角矩形带阴影了

     ShadowDrawable.setShadowDrawable(nextBtn, new int[]{
                    Color.parseColor("#B7FFE7"), Color.parseColor("#ACFFE4")},  DensityUtil.dsToPx(activity, 111),
            Color.parseColor("#CAFFEE"), 20, 0, DensityUtil.dsToPx(activity, 8));

效果图如下在这里插入图片描述

代码并不完善,只是做了单色和渐变色的下阴影,还需要写左右上阴影,对图片的阴影等,但是方式基本不变

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值