[IOS]一种实现view外部点击事件的方法

[IOS]一种实现view外部点击事件的方法

最近做一个效果,点击弹窗view外部的区域使弹窗消失退出。查阅资料,一般网上给出的解决方法多是以下几种:

  • 在一个覆盖全屏的view中添加subview为该弹窗view,然后用touchBegin或者touchEnd方法实现
  • 在覆盖全屏的UIButton下添加subview为该弹窗view,然后给UIButton添加selector
  • 使用hitTest:withEvent方法实现

第一二种方法,还只是限于一个区域内的触摸有效,可能存在风险;第三种方法,系统在一次触摸事件内会调用两次。我针对以上几种方法做到了综合,提供一个更加简便可靠的方法来实现view外部点击事件响应。


首先看这篇文章的图示:http://www.cocoachina.com/ios/20160108/14897.html
系统在判断点击事件时,会先后通过两个方法来判断点击事件在哪里:
- hitTest:withEvent
- pointInside:withEvent

第一个方法在父view返回点击CGPoint落点的subview,第二个方法subview返回BOOL表示落点是否在此subview中。举个例子,当我们给出一个UIButton *btn,hitTest:withEvent返回btn,紧接着btn实现pointInside:withEvent返回true,那么该触摸事件就会在btn中处理。根据这个思路,就构造出了实现view外点击事件实现方法。

  1. 创建一个新的interface继承UIButton
@interface TestBtn: UIButton  
@property (nonmatic, assign) BOOL isClick;
@end
@implement TestBtn
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
    if(_isClick){
        _isClick = NO;
        return YES;
    }
    else{
        return NO;
    }
}
@end

这里TestBtn重写了pointInside:withEvent,当判断是触碰了view外部时返回YES。

  1. 在弹窗view中添加新的按钮:
TestBtn *btn = [[TestBtn alloc] init];
[btn addTarget:self action:@selector(TouchOutside) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btn];

注意这里的btn是没有给frame的,即frame为CGRectZero,所以在该view中,点击事件是不可能触发btn的。

  1. 重写弹窗view的hitTest:withEvent
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    UIView *view = [super hitTest:point wihtEvent:event];
    if(view == nil){
        view = btn; //这里假设btn为全局量
        btn.isClick = YES;
    }
    return view;
}

使用[super hitTest:point wihtEvent:event]可以获得当前view内点击的subview,如果为nil,则点击了view的外部,这时我们返回之前的btn。而btn的pointInside:withEvent返回YES,则系统会根据UIControlEvent响应btn的selector,即不影响view本身组件的工作,也不需要外扩一个全屏view,也不会被多次调用,同时还能响应丰富的UIControlEvent,可谓一举多得。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值