引导蒙版
引导蒙版分为三部分
1、高亮显示的目标布局
2、围绕着目标布局的围栏布局
3、用于提示的蒙版布局
DEMO地址:https://github.com/chaozhouzhang/CustomProgressView
GuideMask guideMask = new GuideMask.Builder(this)//蒙版所在activity.setMaskActivity(this)//目标布局.setTargetView(mIvTest)//蒙版背景颜色包括透明度.setBgColor(Color.parseColor("#40000000"))//蒙版布局.setMaskLayout(R.layout.layout_mask)//关闭蒙版的按钮.setMaskCloseId(R.id.btn_close)//围栏与目标布局的距离.setFencePadding(5,5,5,5)//围栏布局四角的角度.setFenceRadius(100).build();GuideMaskSet guideMaskSet = new GuideMaskSet();
//添加蒙版
guideMaskSet.addGuide(guideMask);
//显示所有蒙版
guideMaskSet.show();
1、自定义FrameLayout
在ViewGroup中,初始化时设置了WILL_NOT_DRAW,设置WILL_NOT_DRAW之后,onDraw()不会被调用,目的是略过绘制的过程,优化了性能。所以,在写自定义ViewGroup布局时,如果需要调用onDraw()进行绘制,则需要在初始化时候,调用setWillNotDraw(false)。
setWillNotDraw(false);
2、使用LayoutInflater解析蒙版布局,并添加到当前自定义布局中
配置root为当前自定义布局,配置attachToRoot为true,也就是解析蒙版布局结束后,直接添加到当前自定义布局中。
LayoutInfalter的使用与源码解析可以看本公众号的文章:
LayoutInfalter的使用与源码解析
mMaskLayoutView = LayoutInflater.from(mMaskActivity).inflate(mMaskLayout, this, true);
3、将自定义布局添加到activity的content布局中
添加:
mContentParent.post(new Runnable() {@Overridepublic void run() {//显示蒙版,也就是将当前蒙版加到mContentParent的FrameLayout布局上mContentParent.addView(GuideMask.this, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));}
});
找到关闭蒙版的ID控件,点击后将自定义布局从activity的content布局中移除:
if (mCloseId != 0) {//在蒙版布局中找到点击关闭蒙版的控件mMaskLayoutView.findViewById(mCloseId).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {dismiss();if (mOnDismissListener != null) {mOnDismissListener.onDismiss();}}});
}
移除:
public void dismiss() {mContentParent.post(new Runnable() {@Overridepublic void run() {//关闭蒙版,也就是将当前蒙版从mContentParent的FrameLayout布局上移除mContentParent.removeView(GuideMask.this);}});
}
4、绘制围栏布局,以突出目标布局
4.1、设置围栏的画笔
图像过渡模式,设置为清除模式,用于显示目标布局:
//首先xfermode绘图需要两部分,DST,SRC 两种。可以理解为DST 在下边,SRC在上面。也就是说DST先绘制,SRC 后绘制。
//PorterDuff.Mode.CLEAR:清除模式,[0, 0],即图像中所有像素点的alpha和颜色值均为0。
PorterDuff.Mode mode = PorterDuff.Mode.CLEAR;
mFenceClearMode = new PorterDuffXfermode(mode);
//这个方法用于设置图像的过渡模式,所谓过渡是指图像的饱和度、颜色值等参数的计算结果的图像表现。
//设置围栏区域为清除模式,以达到显示目标布局的目的
mFencePaint.setXfermode(mFenceClearMode);
设置画笔遮罩滤镜,用于凸出目标布局:
//设置画笔遮罩滤镜,传入BlurMaskFilter或EmbossMaskFilter,前者为模糊遮罩滤镜而后者为浮雕遮罩滤镜。
//如果应用启用了硬件加速,将看不到任何阴影效果。
mFencePaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.INNER));
//关闭当前View的硬件加速。
setLayerType(LAYER_TYPE_SOFTWARE, null);
4.2、onDraw绘制围栏
获取目标布局和content布局的位置坐标:
/*** 获取当前蒙版所目标的布局的坐标位置。*/
mTargetView.getGlobalVisibleRect(mTargetRect);
/*** getGlobalVisibleRect()是View可见区域相对与屏幕来说的坐标位置。* getLocalVisibleRect()是View可见区域想对于自己坐标的位置。* 获取当前蒙版所在activity根布局的坐标位置。*/
mContentParent.getGlobalVisibleRect(mContentRect);
计算围栏布局的位置坐标:
/*** 需要绘制的坐标位置*/
int topMargin = mContentRect.top;
int left = mTargetRect.left - mPaddingLeft;
mFenceRectF.left = left;
int right = mTargetRect.right + mPaddingRight;
mFenceRectF.right = right;
int top = mTargetRect.top - mPaddingTop - topMargin;
mFenceRectF.top = top;
int bottom = mTargetRect.bottom + mPaddingBottom - topMargin;
mFenceRectF.bottom = bottom;
/*** rx:x方向上的圆角半径。* ry:y方向上的圆角半径。*/
canvas.drawRoundRect(mFenceRectF, mRadius, mRadius, mFencePaint);
5、建造者模式构建蒙版
GuideMask guideMask = new GuideMask.Builder(this)//蒙版所在activity.setMaskActivity(this)//目标布局.setTargetView(mIvTest)//蒙版背景颜色包括透明度.setBgColor(Color.parseColor("#40000000"))//蒙版布局.setMaskLayout(R.layout.layout_mask)//关闭蒙版的按钮.setMaskCloseId(R.id.btn_close)//围栏与目标布局的距离.setFencePadding(5,5,5,5)//围栏布局四角的角度.setFenceRadius(100).build();
6、整合蒙版集合,关闭蒙版后显示下一个蒙版
/*** 添加蒙版* @param guideMask*/
public void addGuide(GuideMask guideMask) {mGuideMasks.add(guideMask);guideMask.setOnDismissListener(new GuideMask.OnDismissListener() {@Overridepublic void onDismiss() {//关闭后显示下一个蒙版int nextPosition = mPosition + 1;if (mGuideMasks.size() > nextPosition) {GuideMask next = mGuideMasks.get(nextPosition);mPosition++;next.show();}}});
}
推荐阅读
你亲手写的代码,正在出卖你
深夜,聊聊架构设计
深夜,分享一个Git小技巧
编程·思维·职场
欢迎扫码关注