package com.kyleduo.blurpopupwindow; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.support.annotation.ColorInt; import android.support.annotation.IntRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.Px; import android.util.AttributeSet; import android.widget.LinearLayout; /** * Created by kyle on 2017/3/23. */ public class ShadowContainer extends LinearLayout { public static final int DEFAULT_SHADOW_COLOR = 0x20000000; public static final int DEFAULT_SHADOW_RADIUS_DP = 8; private int mShadowRadius; private int mShadowColor; private ShadowDrawable mShadowDrawable; private float mDensity; public ShadowContainer(Context context) { this(context, null); } public ShadowContainer(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public ShadowContainer(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(attrs); } protected void init(AttributeSet attrs) { setLayerType(LAYER_TYPE_SOFTWARE, null); mDensity = getResources().getDisplayMetrics().density; mShadowRadius = dp2px(DEFAULT_SHADOW_RADIUS_DP); mShadowColor = 0xE0BFCDE6; if (attrs != null) { TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.ShadowContainer); mShadowColor = ta.getColor(R.styleable.ShadowContainer_sc_shadowColor, mShadowColor); ta.recycle(); } mShadowDrawable = new ShadowDrawable(mDensity); mShadowDrawable.setShadow(mShadowRadius, mShadowColor); mShadowDrawable.setInset(mShadowRadius, mShadowRadius); super.setBackgroundDrawable(mShadowDrawable); setPadding( getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom()); } private int dp2px(float dp) { return (int) (mDensity * dp); } @Override public void setBackgroundColor(@ColorInt int color) { mShadowDrawable.setBackgroundColor(color); } @Override public void setBackgroundDrawable(Drawable background) { // do nothing } public ShadowDrawable getShadowDrawable() { return mShadowDrawable; } @Override public void setPadding(@Px int left, @Px int top, @Px int right, @Px int bottom) { left += mShadowRadius; top += mShadowRadius; right += mShadowRadius; bottom += mShadowRadius; super.setPadding(left, top, right, bottom); } public void setShadowRadius(int shadowRadius) { int pl = getPaddingLeft() - mShadowRadius; int pt = getPaddingTop() - mShadowRadius; int pr = getPaddingRight() - mShadowRadius; int pb = getPaddingBottom() - mShadowRadius; mShadowRadius = shadowRadius; mShadowDrawable.setShadow(mShadowRadius, mShadowColor); mShadowDrawable.setInset(mShadowRadius, mShadowRadius); setPadding(pl, pt, pr, pb); } public void setShadowColor(int shadowColor) { mShadowColor = shadowColor; mShadowDrawable.setShadow(mShadowRadius, mShadowColor); invalidate(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST) { widthMeasureSpec = MeasureSpec.makeMeasureSpec( (int) Math.min(MeasureSpec.getSize(widthMeasureSpec), getResources().getDisplayMetrics().widthPixels * 0.8f), MeasureSpec.AT_MOST ); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } public static class ShadowDrawable extends Drawable { private Paint mPaint; private RectF mRectF; private int mBackgroundColor; private int mInsetX, mInsetY; private float mDensity; private int[] mBackgroundColors; private int mCornerRadius; private LinearGradient mLinearGradient; public ShadowDrawable(float density) { mDensity = density; mBackgroundColor = 0xFFFFFFFF; mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mRectF = new RectF(); mPaint.setColor(mBackgroundColor); mPaint.setStyle(Paint.Style.FILL); mCornerRadius = dp2px(6); } public void setInset(int insetX, int insetY) { mInsetX = insetX; mInsetY = insetY; } private int dp2px(float dp) { return (int) (mDensity * dp); } @Override public void draw(@NonNull Canvas canvas) { mRectF.set(getBounds()); mRectF.inset(mInsetX, mInsetY); if (mBackgroundColors != null) { mLinearGradient = new LinearGradient(mRectF.left, mRectF.top, mRectF.right, mRectF.bottom, mBackgroundColors, new float[]{0, 1.f}, Shader.TileMode.CLAMP); mPaint.setShader(mLinearGradient); } canvas.drawRoundRect(mRectF, mCornerRadius, mCornerRadius, mPaint); } @Override public void setAlpha(@IntRange(from = 0, to = 255) int alpha) { mPaint.setAlpha(alpha); } @Override public void setColorFilter(@Nullable ColorFilter colorFilter) { mPaint.setColorFilter(colorFilter); } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } public void setShadow(int radius, int color) { mPaint.setShadowLayer(radius, 0, 0, color); invalidateSelf(); } public void setBackgroundColor(int backgroundColor) { mBackgroundColor = backgroundColor; invalidateSelf(); } public LinearGradient getLinearGradient() { return mLinearGradient; } public void setColors(int[] colors) { mBackgroundColors = colors; invalidateSelf(); } public void setCornerRadius(int cornerRadius) { mCornerRadius = cornerRadius; invalidateSelf(); } } }