iOS下点击任意空白Dismiss当前自定义的AlertView

869 查看

iOS下原生的UIAlertView/UIActionSheet/UIAlertController有时候无法满足我们的需求,我们就会自定义一些弹出框。一般的自定义方案通常是定义一个UIView或者UIView的子类,然后在上面添加一些组件,最后添加到我们指定的parentView上,中间可能还会加几个比较炫酷的动画,这样就达到了我们某些弹出框或者菜单的效果。问题出在如果我们添加到某个View上,但是该View不是全屏的View,我们点击某些地方可能就无法获取到触摸事件,我们的菜单就无法得到响应。

我们定义菜单的时候一般会设计如下所示的两个方法:

- (NSInteger)showInView:(UIView *)view animated:(BOOL)animated;
- (void)dismissAnimated:(BOOL)animated

每当我们需要展示菜单的时候,我们就调用showInView:方法,把菜单添加到view上,反之,当菜单需要结束的时候,就会被dismiss。

之前也有一篇自定义菜单的文章:Block代码继续执行的AlertView,当时的重点不在于介绍AlertView,大家可以下载体验下。

很多时候我们设计的菜单都是非阻塞用户操作的,意思就是点击空白的时候,不能因为有菜单,而影响用户的操作,至少是点击空白的时候,要将菜单消失掉。当我们的view不是全屏的时候,我们如何能做到点击view区域外面还能dismiss当前的菜单呢?

之前的文章介绍过iOS的事件分发模块,大家可以查看之前的博客get这些知识,HitTest其实是给View第一次机会,去处理一些东西。有一点值得肯定的是,如果touchEvent发生在View’s的frame之外,则该View无法检测到这个touchEvent。所以我们要想实现博客所描述的功能,我们只能依赖于新插入的View。思路很简单,每次菜单展示的时候,插入一个透明的View到当前的window上,抓住hitTest给的这次机会,去根据当前情况分发事件。

1、如果点击区域在菜单内,则把事件分发给菜单

2、否则则直接dismiss掉菜单

这里提供一些简单的事件分发代码,以供大家参考

然后在show的时候,将self.hitTestView添加到window上,dismiss的时候,从window移除。

这样,就实现了我们的需求,思路比较简单,就是在window的最顶层添加一个View用于检测触摸事件,当检测到事件之后,根据当前条件来处理事件。

大家可以去我的github下载STKitDemo,里面有STAlertView的相关的实现,使用方式在组件->查看大图->菜单中可以看到。