一,可行行分析
上篇《自定义ShadowLayout矢量阴影布局》我们讲过CardView缺陷,本篇是为了解决上一篇全方向的阴影。
技术方面
这次我们利用MaskFilter实现。
二、关于MaskFilter
一、setMaskFilter(MaskFilter maskfilter)
setMaskFilter(MaskFilter maskfilter)是paint中的方法,它可以用来对图像进行一定的处理。这个方法需要传入一个MaskFilter对象。但MaskFilter类中没有任何实现方法,所以我们就要认识下它的两个子类BlurMaskFilter和EmbossMaskFilter,前者为模糊遮罩滤镜而后者为浮雕遮罩滤镜。
public BlurMaskFilter(float radius, Blur style)
- float radius:用来定义模糊半径,同样是高斯模糊算法。
- Blur style:发光样式,有内发光、外发光、和内外发光,分别对应:Blur.INNER(内发光)、Blur.SOLID(外发光)、Blur.NORMAL(内外发光)、Blur.OUTER(仅发光部分可见),
canvas.drawColor(Color.BLACK);
canvas.drawText("正常",30,100,paint);
Paint paint1 = new Paint();
paint1.setColor(Color.RED);
paint1.setStyle(Paint.Style.FILL);
canvas.drawCircle(300, 100, 50, paint1);
canvas.drawText("INNER",0,250,paint);
Paint paint2 = new Paint();
paint2.setColor(Color.RED);
paint2.setStyle(Paint.Style.FILL);
paint2.setMaskFilter(new BlurMaskFilter(50, BlurMaskFilter.Blur.INNER));
canvas.drawCircle(300, 250, 50, paint2);
canvas.drawText("OUTER",0,400,paint);
Paint paint3 = new Paint();
paint3.setColor(Color.RED);
paint3.setStyle(Paint.Style.FILL);
paint3.setMaskFilter(new BlurMaskFilter(50, BlurMaskFilter.Blur.OUTER));
canvas.drawCircle(300, 400, 50, paint3);
canvas.drawText("NORMAL",0,550,paint);
Paint paint4 = new Paint();
paint4.setColor(Color.RED);
paint4.setStyle(Paint.Style.FILL);
paint4.setMaskFilter(new BlurMaskFilter(50, BlurMaskFilter.Blur.NORMAL));
canvas.drawCircle(300, 550, 50, paint4);
同样也可以处理图片
paint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));
paint.setColor(Color.GREEN);
canvas.drawBitmap(mBitmap, null, new RectF(100, 100, 100 + mBitmap.getWidth(), mBitmap.getHeight() + 100), paint);
paint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));
canvas.drawBitmap(bitmap, null, new RectF(100, 300, 100 + bitmap.getWidth(), bitmap.getHeight() + 300), paint);
二、ShadowBoxLayout实现
源码文件
public class ShadowBoxLayout extends FrameLayout {
private float mOutLineOffset = 1;
private Paint mShadowPaint;
private int mShadowColor; //阴影颜色
private float mRadius = 1; //阴影转角半径
private RectF mRect = null;
public ShadowBoxLayout(Context context) {
this(context, null);
}
public ShadowBoxLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ShadowBoxLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
if (attrs == null) {
return;
}
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ShadowBoxLayout);
mShadowColor = a.getColor(R.styleable.ShadowBoxLayout_shadowBox_color, 0x99333333);
mRadius = a.getDimension(R.styleable.ShadowBoxLayout_shadowBox_radius, 1);
mOutLineOffset = a.getDimension(R.styleable.ShadowBoxLayout_shadowBox_outLineOffset, 1);
if(mRadius<=0){
mRadius = 1;
}
a.recycle();
init();
}
private void init() {
mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mShadowPaint.setColor(mShadowColor);
mShadowPaint.setStyle(Paint.Style.FILL);
mShadowPaint.setAntiAlias(true);
setWillNotDraw(false); //开启viewgroup 绘制模式
setLayerType(LAYER_TYPE_SOFTWARE, null);
int padding = (int) mOutLineOffset;
setPadding(padding,padding,padding,padding);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
int childCount = getChildCount();
if(childCount==0) return;
View view = getChildAt(0);
mRect = new RectF(view.getX(), view.getY(), view.getX() + view.getWidth(), view.getY()+view.getHeight());
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
int childCount = getChildCount();
if(childCount>1) throw new RuntimeException("child count > 1 ! ");
super.addView(child, index, params);
}
@Override
protected boolean addViewInLayout(View child, int index, ViewGroup.LayoutParams params) {
int childCount = getChildCount();
if(childCount>1) throw new RuntimeException("child count > 1 ! ");
return super.addViewInLayout(child, index, params);
}
@Override
protected void dispatchDraw(Canvas canvas) {
if(mShadowPaint==null) {
super.dispatchDraw(canvas);
return;
}
mShadowPaint.setMaskFilter(new BlurMaskFilter(mRadius, BlurMaskFilter.Blur.SOLID));
canvas.drawRoundRect(mRect, mRadius, mRadius, mShadowPaint);
super.dispatchDraw(canvas);
}
}
属性文件
<declare-styleable name="ShadowBoxLayout">
<attr name="shadowBox_color" format="color|reference"/>
<attr name="shadowBox_radius" format="dimension|reference"/>
<attr name="shadowBox_outLineOffset" format="dimension|reference"/>
</declare-styleable>
使用方法
<com.cn.scrolllayout.view.ShadowBoxLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:shadowBox_radius="5dp"
app:shadowBox_color="#99333333"
app:shadowBox_outLineOffset="5dp"
>
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:scaleType="centerCrop"
android:src="@drawable/img_bird" />
</com.cn.scrolllayout.view.ShadowBoxLayout>