給佈局,控制元件新增陰影,包裹它設定陰影顏色,長度,偏移即可
阿新 • • 發佈:2018-11-16
public class ShadowLayout extends FrameLayout { private int mShadowColor; private float mShadowRadius; private float mCornerRadius; private float mDx; private float mDy; 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); } } public void setInvalidateShadowOnSizeChanged(boolean invalidateShadowOnSizeChanged) { mInvalidateShadowOnSizeChanged = invalidateShadowOnSizeChanged; } public void invalidateShadow() { mForceInvalidateShadow = true; requestLayout(); invalidate(); } private void initView(Context context, AttributeSet attrs) { initAttributes(context, attrs); int xPadding = (int) (mShadowRadius + Math.abs(mDx)); int yPadding = (int) (mShadowRadius + Math.abs(mDy)); setPadding(xPadding, yPadding, xPadding, yPadding); } @SuppressWarnings("deprecation") private void setBackgroundCompat(int w, int h) { Bitmap bitmap = createShadowBitmap(w, h, mCornerRadius, mShadowRadius, mDx, mDy, mShadowColor, Color.TRANSPARENT); 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 (attr == null) { return; } try { mCornerRadius = attr.getDimension(R.styleable.ShadowLayout_sl_cornerRadius, getResources().getDimension(R.dimen.default_corner_radius)); mShadowRadius = attr.getDimension(R.styleable.ShadowLayout_sl_shadowRadius, getResources().getDimension(R.dimen.default_shadow_radius)); mDx = attr.getDimension(R.styleable.ShadowLayout_sl_dx, 0); mDy = attr.getDimension(R.styleable.ShadowLayout_sl_dy, 0); mShadowColor = attr.getColor(R.styleable.ShadowLayout_sl_shadowColor, getResources().getColor(R.color.default_shadow_color)); } finally { attr.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.ALPHA_8); 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, mDx, mDy, shadowColor); } canvas.drawRoundRect(shadowRect, cornerRadius, cornerRadius, shadowPaint); return output; }
<declare-styleable name="ShadowLayout"> <attr name="sl_cornerRadius" format="dimension"/> <attr name="sl_shadowRadius" format="dimension"/>//陰影寬度 <attr name="sl_shadowColor" format="color"/>//陰影顏色 <attr name="sl_dx" format="dimension"/>//偏移 <attr name="sl_dy" format="dimension"/> </declare-styleable>
用例:
<com.ShadowLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/gf_tree_gif" android:layout_marginLeft="6dp" android:layout_marginRight="6dp" android:layout_marginTop="-40dp" app:sl_dx="2dp" app:sl_dy="2dp" app:sl_shadowColor="#1Aefefef" app:sl_shadowRadius="8dp" > <任意佈局> </ShadowLayout>