引导遮罩层方案实现总结

9,875 阅读4分钟

背景

最近公司在重构一个App,大功能基本上已经完成,正想可以缓一口气研究研究flutter了,组长让我先验证一下之前的引导页方案,他初步验证,看下来似乎有点问题。由于App改版,很多入口发生了变化,所以出于用户体验,加了一些引导,我之前有做过类似引导页,但跟这次的实现方案不太一样。一开始组长已经让团队其他成员研究了,报告上来说有现成库可解决,很方便。我去Github验证了一下,发现并没有那么简单。

我们要实现的效果如下图,单页面有多个遮罩步骤,单次遮罩可能有多个遮罩层,遮罩有带圆角,有不带圆角,文字图片按钮等位置均需要自定义。

一开始说有库可以解决,我也就没多加思考,此处贴出之前找的库的地址KSGuideController,后来的思路也有借鉴此库的做法,只是把该定制化的部分还给使用者自己去描述,增加了库的可用性。

问题

这个库做的还是蛮漂亮的,但对我们的项目却不适用,概括大概有3点:

  • 引导页布局不够自定义,只有一个箭头图片和文字描述,我们项目遮罩页的元素过多不够呈现
  • 遮罩单次只有一个,我们项目部分遮罩有2个同时呈现的场景
  • 他是一个固定的View,而我们有tableview,他那种只传遮罩View的思路是好的,使用者较无脑,但在TableView或者ScrollView中并不适用,传过去之后,他并不能定位到准确frame

思路

既然问题找到了,下面就是解决的问题的思路了:

  • 引导页不够自定义,这种高度自定义的界面,理应由使用者自己去布局,遮罩VC你爱做成什么样就做成什么样,我只负责帮你遮罩
  • 遮罩页具体该遮罩几个,应该是使用者告诉我的,库不应该局限使用者
  • 传View并不能让我得到精确的位置,那位置应该由使用者告诉我

分析下来,我们要做的其实就很简单了,负责做一个遮罩VC,由外面传进来遮罩的Frame,我们负责把frame遮起来。所以,一开始我设计了传入一个frame数组,我负责对frame数组遍历进行遮罩,点击之后dissmiss并且callback给使用者,然后使用者是要再次present一个遮罩vc还是做其他操作皆可,但后来尝试下来,发现dissmiss之后再present有两点不好的地方。

  • 第一点,反复callback,使用感受很傻,并且容易循环引用,当页面需要3个以上的遮罩层之后,简直是噩梦
  • 第二点,就算把动画关了,也还是有一个闪屏效果,体验很不好

所以思考了一下,一个页面的多个遮罩步骤应该是一体的,用key-value的形式传进来,key代表index,value传frame数组,内部解析由我处理,不同的index重新reload遮罩,这样,单页面的多步骤遮罩就会很顺畅,全部遍历完成后再dissmiss遮罩层,效果完美!!!

demo中也给出了如何提取cell这种动态view对于整个页面的相对位置。原则上来讲,只要你取的frame准确就没问题。当前库支持传入遮罩层背景色、遮罩层圆角、点击之后是否dismiss以及dismiss回调。

    public var maskFrame: [Int: [CGRect]] = [:]
    public var maskColor: UIColor = UIColor(red: 0/255.0, green: 0/255.0, blue: 0/255.0, alpha: 0.5)
    public var cornerRadius: CGFloat = 0
    public var touchShouldDismiss: Bool = true
    public var dismissCallback: (() -> Void)?

总结

库的核心代码其实很少,问题理清之后,自己写也花不了多少时间。本文主要是提出解决问题的思路,Github上有太多太多的库,但并不是都能为我们所用,有时候乍一看是能用,但真正思考使用场景的时候,却发现还是有很多差异。我们可以吸收里面好的思想,并且自己手动撸一个,当然自己手动撸的过程是一个思考如何让这个库变得更有效、更易用的过程,而不仅仅是满足自己的使用场景。一个库如何才能封装到别人能用、易用是一个持续思考的过程,并且没有终点。

Github地址:ZSYMaskView

如果这篇文章能给到你们启发,就点个赞👍👍👍吧

如果这个库有帮到你们,就点个star🌟🌟🌟吧