设置属性:
<declare-styleable name="ShadowLayout">
<attr name="sfl_backgroundRound" format="dimension" />
<attr name="sfl_shadowWidth" format="dimension" />
<attr name="sfl_shadowColor" format="color" />
<attr name="sfl_background" format="color" />
<attr name="sfl_offsetX" format="dimension" />
<attr name="sfl_offsetY" format="dimension" />
</declare-styleable>
代码实现:
public class ShadowLayout extends FrameLayout {
private int shadowWidth;//阴影宽度
private int backgroundRound;//背景圆角
private int shadowColor;//阴影颜色
private int backgroundColor;//背景颜色
private int offsetX;//上下偏移(正数上偏移,负数下偏移)
private int offsetY;//左右偏移(正数左偏移,负数右偏移)
private boolean mInvalidateShadowOnSizeChanged = true;
private boolean mForceInvalidateShadow = false;
public ShadowLayout(Context context) {
super(context);
initView(context, null);
}
public ShadowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context, attrs);
}
public ShadowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context, attrs);
}
@Override
protected int getSuggestedMinimumWidth() {
return 0;
}
@Override
protected int getSuggestedMinimumHeight() {
return 0;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (w > 0 && h > 0 && (getBackground() == null || mInvalidateShadowOnSizeChanged || mForceInvalidateShadow)) {
mForceInvalidateShadow = false;
setBackgroundCompat(w, h);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mForceInvalidateShadow) {
mForceInvalidateShadow = false;
setBackgroundCompat(right - left, bottom - top);
}
}
private void initView(Context context, AttributeSet attrs) {
initAttributes(context, attrs);
int xPadding = (int) (shadowWidth + Math.abs(offsetX));
int yPadding = (int) (shadowWidth + Math.abs(offsetY));
setPadding(xPadding, yPadding, xPadding, yPadding);
}
@SuppressWarnings("deprecation")
private void setBackgroundCompat(int w, int h) {
Bitmap bitmap = createShadowBitmap(w, h, backgroundRound, shadowWidth, offsetX, offsetY, shadowColor, backgroundColor);
BitmapDrawable drawable = new BitmapDrawable(getResources(), bitmap);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
setBackgroundDrawable(drawable);
} else {
setBackground(drawable);
}
}
private void initAttributes(Context context, AttributeSet attrs) {
TypedArray attr = getTypedArray(context, attrs, R.styleable.ShadowLayout);
if (attrs != null) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ShadowLayout);
shadowWidth = typedArray.getDimensionPixelSize(R.styleable.ShadowLayout_sfl_shadowWidth, 0);
backgroundRound = typedArray.getDimensionPixelSize(R.styleable.ShadowLayout_sfl_backgroundRound, 0);
shadowColor = typedArray.getColor(R.styleable.ShadowLayout_sfl_shadowColor, Color.parseColor("#ffffff"));
backgroundColor = typedArray.getColor(R.styleable.ShadowLayout_sfl_background, Color.parseColor("#ffffff"));
offsetX = typedArray.getDimensionPixelSize(R.styleable.ShadowLayout_sfl_offsetX, 0);
offsetY = typedArray.getDimensionPixelSize(R.styleable.ShadowLayout_sfl_offsetY, 0);
typedArray.recycle();
}
}
private TypedArray getTypedArray(Context context, AttributeSet attributeSet, int[] attr) {
return context.obtainStyledAttributes(attributeSet, attr, 0, 0);
}
private Bitmap createShadowBitmap(int shadowWidth, int shadowHeight, float cornerRadius, float shadowRadius,
float dx, float dy, int shadowColor, int fillColor) {
Bitmap output = Bitmap.createBitmap(shadowWidth, shadowHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
RectF shadowRect = new RectF(
shadowRadius,
shadowRadius,
shadowWidth - shadowRadius,
shadowHeight - shadowRadius);
if (dy > 0) {
shadowRect.top += dy;
shadowRect.bottom -= dy;
} else if (dy < 0) {
shadowRect.top += Math.abs(dy);
shadowRect.bottom -= Math.abs(dy);
}
if (dx > 0) {
shadowRect.left += dx;
shadowRect.right -= dx;
} else if (dx < 0) {
shadowRect.left += Math.abs(dx);
shadowRect.right -= Math.abs(dx);
}
Paint shadowPaint = new Paint();
shadowPaint.setAntiAlias(true);
shadowPaint.setColor(fillColor);
shadowPaint.setStyle(Paint.Style.FILL);
if (!isInEditMode()) {
shadowPaint.setShadowLayer(shadowRadius, dx, dy, shadowColor);
}
canvas.drawRoundRect(shadowRect, cornerRadius, cornerRadius, shadowPaint);
return output;
}
}
