android原生的阴影效果,一般都是用CardView来实现
CardView的不足:
1、阴影颜色无法修改
2、阴影显示的位置不可控
根据CardView阴影实现{@link android.support.v7.widget.RoundRectDrawableWithShadow},在它的基础上实现自定义阴影Drawable,阴影颜色、位置可控
GitHub开源库地址
1、root build.gradle中添加仓库地址:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
2、app module build.gradle中添加依赖
dependencies {
implementation 'com.github.zhangjianliang110:color-shadow_drawable:v1.0.1
}
3、Demo
public class MainActivity extends AppCompatActivity {
private ImageView mIvTest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIvTest = findViewById(R.id.ivTest);
ViewCompat.setBackground(mIvTest, getShadowBg(
ShadowDrawable.ShadowCorner.ALL, ShadowDrawable.ShadowSide.ALL
));
}
private ShadowDrawable getShadowBg(int cornerType, int sideType) {
Resources resources = getResources();
ColorStateList backgroundColor = ColorStateList.valueOf(resources.getColor(android.R.color.white));//设置背景色
ShadowDrawable shadowBg = new ShadowDrawable(resources, backgroundColor, dip2px(25), dip2px(3), dip2px(6));
shadowBg.setShadowCorner(cornerType);
shadowBg.setShadowSide(sideType);
int startColor = resources.getColor(R.color.shadow_start_color);//阴影内侧颜色
int endColor = resources.getColor(R.color.shadow_end_color);//阴影外侧颜色
shadowBg.setShadowColor(startColor, endColor);
return shadowBg;
}
private int dip2px(float dipValue) {
if (dipValue == 0) {
return 0;
}
final float scale = getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
}
package com.test.testapp.view;
import com.test.testapp.R;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.Nullable;
/**
* 阴影图
*
* 该阴影的计算方式跟CardView阴影计算完全一致,这里只是把阴影绘制拆分成每个角、每条边,以及绘制起点、终点的控制,阴影颜色控制
*
* CardView阴影颜色不可选、不能控制只显示其中某一边不显示阴影,无法达到设计效果
* {@link android.support.v7.widget.RoundRectDrawableWithShadow }
*
* Created by zhangjianliang on 2018/12/13
*
* 使用方式:
*
View view = findViewById(R.id.xxx);
Resources resources = getResources();
ColorStateList backgroundColor = ColorStateList.valueOf(resources.getColor(R.color.white));//设置背景色
ShadowDrawable shadow = new ShadowDrawable(resources, backgroundColor, CommonUtils.dip2px(2), CommonUtils.dip2px(5),
CommonUtils.dip2px(5));
shadow.setShadowColor(ColorUtils.getColor(R.color.common_color_fd5c59), ColorUtils.getColor(R.color.common_color_ffcfcf));
shadow.setShadowCorner(ShadowDrawable.ShadowCorner.LEFT_TOP);
shadow.setShadowSide(ShadowDrawable.ShadowSide.TOP);
shadow.setBackgroundColor(ColorUtils.getColor(android.R.color.transparent));
shadow.setShadowDistance(0, 0, 0, CommonUtils.dip2px(7));
ViewUtil.setViewBackground(view, shadow);
*
*
*/
package com.stupidbird.view;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.Nullable;
/**
* 阴影图
*
* 该阴影的计算方式跟CardView阴影计算完全一致,这里只是把阴影绘制拆分成每个角、每条边,以及绘制起点、终点的控制,阴影颜色控制
*
* CardView阴影颜色不可选、不能控制只显示其中某一边不显示阴影,无法达到设计效果
* {@link android.support.v7.widget.RoundRectDrawableWithShadow }
*
* Created by zhangjianliang on 2018/12/13
*
* 使用方式:
*
View view = findViewById(R.id.xxx);
Resources resources = getResources();
ColorStateList backgroundColor = ColorStateList.valueOf(resources.getColor(R.color.white));//设置背景色
ShadowDrawable shadow = new ShadowDrawable(resources, backgroundColor, CommonUtils.dip2px(2), CommonUtils.dip2px(5),
CommonUtils.dip2px(5));
shadow.setShadowColor(ColorUtils.getColor(R.color.common_color_fd5c59), ColorUtils.getColor(R.color.common_color_ffcfcf));
shadow.setShadowCorner(ShadowDrawable.ShadowCorner.LEFT_TOP);
shadow.setShadowSide(ShadowDrawable.ShadowSide.TOP);
shadow.setBackgroundColor(ColorUtils.getColor(android.R.color.transparent));
shadow.setShadowDistance(0, 0, 0, CommonUtils.dip2px(7));
ViewUtil.setViewBackground(view, shadow);
*
*
*/
public class ShadowDrawable extends Drawable {
private static final float DEFAULT_SHADOW_MULTIPLIER = 1.5f;
private final RectF mCornerRect = new RectF();
// used to calculate content padding
private static final double COS_45 = Math.cos(Math.toRadians(45));
private float mShadowMultiplier = DEFAULT_SHADOW_MULTIPLIER;
private final int mInsetShadow; // extra shadow to avoid gaps between card and shadow
private Paint mPaint;
private Paint mCornerShadowPaint;
private Paint mEdgeShadowPaint;
private final RectF mCardBounds;
private float mCornerRadius;
private Path mCornerShadowPath;
// actual value set by developer
private float mRawMaxShadowSize;
// multiplied value to account for shadow offset
private float mShadowSize;
// actual value set by developer
private float mRawShadowSize;
private ColorStateList mBackground;
private boolean mDirty = true;
private int mShadowStartColor;
private int mShadowEndColor;
private boolean mAddPaddingForCorners = true;
/**
* If shadow size is set to a value above max shadow, we print a warning
*/
private boolean mPrintedShadowClipWarning = false;
private int mCornerType = ShadowCorner.ALL;//默认四个角都有阴影
private int mSideType = ShadowSide.ALL;//默认四条边都有阴影
/**用于某些情况下,阴影起点/终点需要缩进的情况*/
private int mLeftShadowDistance;//阴影与左边的距离
private int mTopShadowDistance;//阴影与上边的距离
private int mRightShadowDistance;//阴影与右边的距离
private int mBottomShadowDistance;//阴影与下边的距离
/**
* 创建阴影背景
*
* @param backgroundColor 背景色
* @param radius 圆角
* @param shadowSize 阴影宽度
* @param maxShadowSize 阴影最大宽度
*/
public ShadowDrawable(Resources resources, ColorStateList backgroundColor, float radius, float shadowSize,
float maxShadowSize) {
mShadowStartColor = resources.getColor(R.color.shadowview_shadow_start_color);
mShadowEndColor = resources.getColor(R.c