android 圆形图片设置蒙层,轻松搞懂自定义蒙层引导原理

本文详细介绍了自定义蒙层引导视图的核心原理,包括按需加载、确定并高亮目标视图、自定义提示视图的摆放。通过分析如何利用系统API获取视图位置、裁剪路径实现高亮效果,以及如何处理多个引导步骤和控制显示次数,为开发者提供了一种解决界面引导问题的方法。
摘要由CSDN通过智能技术生成

原标题:轻松搞懂自定义蒙层引导原理

本文作者

作者:二两五花肉

链接:

https://kaelinvoker.github.io/Blog/

本文由作者授权发布。

蒙层引导在我们项目中一直的做法都是让UI直接切一整张静态图,这样的做法虽然省事,但带来的后果就是适配性太差,还会出现引导图和下面真正的界面不符的情况,让用户感到莫名其妙。因此,就有必要自定义一个蒙层引导视图来解决这个问题。本篇文章主要是对核心原理实现的剖析。

核心原理分析

自定义引导视图(GuideView)其实最主要的是需要解决三个问题:

引导视图应该是按需加载,在需要展示时浮在整个页面上,展示完毕后从页面视图中移除

确定需要引导的视图位置,并将之高亮

支持自定义提示视图,并根据高亮视图的位置摆放

对于第一个问题,很容易想到GuideView应该继承自帧布局,这样可以保证浮在整个页面上。按需加载的话,可以在需要展示引导时,添加到页面的根视图(即DecorView)上,展示完毕后再从根视图中移除即可解决。并且为了让蒙层布满全屏,应该在添加时,指定宽高为Decorview的宽高。

对于第二个问题,高亮视图的位置,可以通过系统提供的获取屏幕位置的API来解决

publicstaticRectF getRectOnScreen(View view){

if(view == null) {

returnnewRectF();

}

RectF result = newRectF();

int[] pos = newint[ 2];

view.getLocationOnScreen(pos);

result.left = pos[ 0];

result.top = pos[ 1];

result.right = result.left + view.getMeasuredWidth();

result.bottom = result.top + view.getMeasuredHeight();

returnresult;

}

获取到高亮位置后,下一步就是如何高亮?通常的做法就是将高亮位置从整个屏幕当中挖出来,改变屏幕其它位置的背景。

如下图所示:

7fd71ca490d5166eeaf49ddfa5d8d1e8.png

要实现这样的效果,就需要知道画布裁剪的知识。

裁剪共分为:裁剪路径、裁剪矩形、裁剪区域。裁剪后,只能编辑该区域,其它的区域并没有消失!

这里,我们可以选择裁剪路径。因为一般的引导库为了能够更好地引导用户,会在高亮区周围会绘制一些内容。

而路径(path)很好地封装了由直线和曲线构的几何图形,如添加圆形、矩形、圆角矩形、椭圆形甚至一些复杂图形。因此在确定好高亮区位置后,我们也可以根据位置信息通过path完成一些图片的绘制,如圆形:

mPath.addCircle( mDrawRect.centerX(), mDrawRect.centerY(), radius, Path.Direction.CW);

mDrawRect就是高亮区的位置。注意:这里只是在path中描述了图形的轮廓。

继续说裁剪路径。裁剪路径的API有以下两个。

// 方法1

publicboolean clipPath( @NonNullPath path)

// 方法2

publicboolean clipPath( @NonNullPath path, @NonNullRegion.Op op)

方法1默认调用了方法2,只是第二个参数传的值是 Region.Op.INTERSECT

/**

* Intersect the current clip with the specified path.

*

* @parampath The path to intersect with the current clip

* @returntrue if the resulting clip is non-empty

*/

publicbooleanclipPath(@NonNull Path path){

returnclipPath(path, Region.Op.INTERSECT);

}

下面一张图解释下Region.Op 这个参数。它的作用就是在裁剪下多个区域时,当这些区域有重叠的时候,决定重叠部分该如何处理,多次裁剪之后究竟获得了哪个区域。

a3bba78c80ff086b7b7059f9300b6218.png

这里我们需要的是先裁剪出高亮区之外的区域,因为要绘制蒙层背景,但不能绘制到高亮区。所以选择的参数应该是Region.Op.DIFFERENCE。

裁剪后,绘制需要的背景。

绘制完背景后,如果有需要,还可通过画布可以将上面的path中描述的图形再绘制出来。

@Override

protectedvoidonDraw(Canvas canvas){

super.onDraw(canvas);

//以下为伪代码

//第一步:裁剪非高亮区

canvas.clipPath(guideShape.getShapePath(), Region.Op.DIFFERENCE);

//第二步:绘制蒙层背景

canvas.drawColor(mBgColor);

//第三步:如果需要,绘制高亮区内容

if(mEnableDrawShape) {

guideShape.onDraw(canvas);

}

}

注意:ViewGroup默认是不绘制的,因此这里要绘制的话,需要将开关打开。

//需要重写onDraw 设置为 false

setWillNotDraw( false);

第三个问题,外部可以传入布局Id,也可以直接传入View,然后将提示视图添加到自定义的GuideView中。如果传入的是ID,我们内部可以使用布局解析器解析出来,然后再添加。

添加之后,如何摆放呢?这里我们可以通过Margin和Gravity来确定。

具体规则如下:

9ceca866b5ad1389bf26f523b9c95e8d.png

40dd303d408541b877f59a7677e1f76f.png

72e198dd214543b4973b1ec67b4c3a7e.png

到此,一个引导库的核心原理已经全部分析完毕。

其它功能分析

1. 多个引导分步骤如何实现?

可以先定义一个Java Bean对象,用来封装需要的一些参数,如需要引导的视图,提示视图等。然后用集合来保存,每次从集合中取第一个元素中的提示视图,添加到GuideView中,每次添加时,GuideView都要移除所有子视图,保证每次只显示一个引导。同时,添加完毕后,从集合中移除这个元素。这里应该能够想到集合应该用个队列来实现,Java的集合体系中,支持队列的有Deque接口,所有这里可以使用ArrayDeque或者LinkedList。

2. 如何控制引导的显示次数?

这个很容易想到用SP来控制。每次往SP中存取次数,默认只允许一次。当然还可以设定次数上限,或者永久显示用于调试。返回搜狐,查看更多

责任编辑:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值