Android 自定义ShadowBoxLayout 全方向阴影布局

原创
2020/07/12 16:49
阅读数 4.6K

一,可行行分析

上篇《自定义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>

 

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部