首先文章非常简单,代码非常精简,也就是说这里的技术只是打造一个非常方便扩展的view,剩下的事情没有学习成本,只需要跟平常开发一样写布局摆放到指定位置就行,越是精简越是非常容易扩展,整个引导浮层就镂空区域没法使用现成view,或者xml写出来的。
设计思路和扩展原理
1、引导箭头是自己摆放,方便用户定制,自己用布局嵌套就好
2、方便用户随意摆放到任何位置,如对话框、顶层decorview
或者放置到fragment
里面于是我打算设计成一个view,而不是一个封装死的框架.而且这个view只处理镂空形状问题.
3、镂空形状的设计要方便扩展,我采取接口的方式传递画板和画笔 默认实现了圆形和矩形,用户可以轻松实现其他形状定制。
镂空实现原理
超级简单的,我之前看了别人那个就头疼,于是自己着手写了一个镂空的,采用的绘制模式是`
det_out
模式来实现,其实吧,实现方式多种多样的.
首先要说明白一点就是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
*/
}
}