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));
效果图如下
代码并不完善,只是做了单色和渐变色的下阴影,还需要写左右上阴影,对图片的阴影等,但是方式基本不变