首先文章非常简单,代码非常精简,也就是说这里的技术只是打造一个非常方便扩展的view,剩下的事情没有学习成本,只需要跟平常开发一样写布局摆放到指定位置就行,越是精简越是非常容易扩展,整个引导浮层就镂空区域没法使用现成view,或者xml写出来的。

设计思路和扩展原理

1、引导箭头是自己摆放,方便用户定制,自己用布局嵌套就好
2、方便用户随意摆放到任何位置,如对话框、顶层decorview或者放置到fragment里面于是我打算设计成一个view,而不是一个封装死的框架.而且这个view只处理镂空形状问题.
3、镂空形状的设计要方便扩展,我采取接口的方式传递画板和画笔 默认实现了圆形和矩形,用户可以轻松实现其他形状定制。

镂空实现原理

超级简单的,我之前看了别人那个就头疼,于是自己着手写了一个镂空的,采用的绘制模式是`det_out模式来实现,其实吧,实现方式多种多样的.

image.png

首先要说明白一点就是det表示底层图层, src表示顶层的图层
从图中得知,dstout模式 就是把src盖到dstout的右下角,导致右下角消失不见了。

所以我这里是绘制了一个矩形半透明 然后上层 绘制一个要镂空的任意形状, 颜色随便,我这里保持不变。

开源完整地址

https://github.com/qssq/HollowOutView
导入依赖

compile 'cn.qssq666:hollowoutview:0.1'

使用方法

HollowOutView hollowOutView = (HollowOutView) findViewById(R.id.hollowoutview);
        //在中心点100的区域绘制一个50px大小的圆圈 透明区域
        HollowOutView.CiceleHollowedShapeInfo circle=new HollowOutView.CiceleHollowedShapeInfo().setCx(100).setCy(100).setRadius(100);
        hollowOutView.addGuideDrawInfo(circle);
        //添加一个矩形 镂空透明区域 所有单位都是px,自己转换
        HollowOutView.RectHollowedShapeInfo rect=new HollowOutView.RectHollowedShapeInfo().setHeight(100).setWidth(90).setLeft(400).setTop(800);
        hollowOutView.addGuideDrawInfo(rect);
        hollowOutView.applyChanage();

非完整代码 HollowOutView镂空view代码如下.

/**
 * Created by qssq on 2018/4/29 qssq666@foxmail.com
 */
public class HollowedOutView extends View {

    public Paint getPaint() {
        return paint;
    }

    private Paint paint;

    public HollowedOutView(Context context) {
        super(context);
        init(context);
    }

    public HollowedOutView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    protected void init(Context context) {


        paint = new Paint();
        paint.setFlags(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.parseColor("#7f000000"));//百分之50
        paint.setColor(Color.parseColor("#32000000"));//百分之20
        paint.setColor(Color.parseColor("#c8000000"));//百分之80
        setLayerType(LAYER_TYPE_SOFTWARE, null);//关闭硬件加速

    }

    public HollowedOutView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.drawRect(0, 0, getWidth(), getHeight(), paint);

        Xfermode mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);//从绘制模式图片得知 这种模式会导致挖空的区域消失
        paint.setXfermode(mXfermode);
        for (int i = 0; i < infos.size(); i++) {

            HollowedOutShapeInfoI guideDrawInfo = infos.get(i);
            guideDrawInfo.executeDraw(canvas, paint);

        }
        paint.setXfermode(null);


    }

    protected List<HollowedOutShapeInfoI> infos = new ArrayList<>();

    public void addGuideDrawInfo(HollowedOutShapeInfoI info) {

    }

    public void addGuideDrawInfos(List<HollowedOutShapeInfoI> infos) {
        this.infos.addAll(infos);

    }

    public void clearGuideDrawInfo() {

        infos.clear();
    }

    /**
     * 镂空形状接口 可用户自定义
     */
    public interface HollowedOutShapeInfoI {
        /**
         * 要挖空的形状
         *
         * @param canvas
         * @param paint
         */
        void executeDraw(Canvas canvas, Paint paint);
    }

    public static class RectHollowedShapeInfo implements HollowedOutShapeInfoI {


        public int getLeft() {
            return left;
        }

        public void setLeft(int left) {
            this.left = left;
        }

        public int getTop() {
            return top;
        }

        public void setTop(int top) {
            this.top = top;
        }

        public int getWidth() {
            return width;
        }

        public void setWidth(int width) {
            this.width = width;
        }

        public int getHeight() {
            return height;
        }

        public void setHeight(int height) {
            this.height = height;
        }

        int left;
        int top;
        int width;
        int height;

        @Override
        public void executeDraw(Canvas canvas, Paint paint) {
            canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
        }

    }

    //默认实现的镂空圆形图标


    public static class CiceleHollowedShapeInfo implements HollowedOutShapeInfoI {

        public int getCx() {
            return cx;
        }

        /**
         * 要绘制的圆圈的中心点x坐标
         *
         * @param cx
         */
        public void setCx(int cx) {
            this.cx = cx;
        }

        /**
         * 要绘制的中心点y坐标
         *
         * @return
         */
        public int getCy() {
            return cy;
        }

        public void setCy(int cy) {
            this.cy = cy;
        }

        public int getRadius() {
            return radius;
        }

        public void setRadius(int radius) {
            this.radius = radius;
        }

        int cx;
        int cy;
        /**
         * 圆角半径
         */
        int radius;

        @Override
        public void executeDraw(Canvas canvas, Paint paint) {


            canvas.drawCircle(
                    cx,
                    cy,
                    radius, paint);
        }
        /**
         * 要挖空的形状
         *
         * @param canvas
         */
    }


}
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐