- (void)willMoveToWindow:(UIWindow *)newWindow
{
[selfsetFrame:CGRectMake(0,0,100,100)];
if (!_testBtn)
{
_testBtn = [[UIButtonalloc]initWithFrame:CGRectMake(20,20,60, 60)];
[_testBtnsetBackgroundColor:[UIColorredColor]];
[_testBtnaddTarget:selfaction:@selector(buttonBeClicked:)forControlEvents:UIControlEventTouchUpInside];
[selfaddSubview:_testBtn];
UITapGestureRecognizer *doubleclick = [[UITapGestureRecognizeralloc]initWithTarget:selfaction:@selector(selfViewBeClicked)];
doubleclick.numberOfTapsRequired =1;
doubleclick.cancelsTouchesInView =FALSE;
doubleclick.numberOfTouchesRequired =1 ;
doubleclick.delegate = (id<UIGestureRecognizerDelegate>)self;
[selfaddGestureRecognizer:doubleclick];
}
}
- (void)buttonBeClicked:(id)sender
{
NSLog(@"ButtonClick");
}
- (void)selfViewBeClicked
{
NSLog(@"SelfViewClick");
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
BOOL isInView = [superpointInside:pointwithEvent:event];
if (isInView)
{
NSLog(@"pointInView");
}
else
{
NSLog(@"pointOutView");
}
return isInView;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"touchesBegan");
[supertouchesBegan:toucheswithEvent:event];
}
// 询问delegate是否允许手势接收者接收一个touch对象
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
NSLog(@"UIGestureRecognizer - FliterTouch");
return YES;
}
// 询问一个手势接收者是否应该开始解释执行一个触摸接收事件
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
NSLog(@"UIGestureRecognizer - FliterAction");
return YES;
}
实验1:点击View
打出的Log是:
2015-02-26 14:14:54.701xxxx[21638:110325] pointInView
2015-02-26 14:14:54.702xxxx[21638:110325] pointInView
2015-02-26 14:14:54.702xxxx[21638:110325] UIGestureRecognizer - FliterTouch
2015-02-26 14:14:54.703xxxx[21638:110325] touchesBegan
2015-02-26 14:14:54.806xxxx[21638:110325] UIGestureRecognizer - FliterAction
2015-02-26 14:14:54.807 xxxx[21638:110325] SelfViewClick
如果FliterTouch返回NO则touchesBegan之后的不走。(touchesBegan会走)
如果FliterAction返回NO则SelfViewClick不走,只是绑定的响应函数不走。
实验2:点击Button
打出的Log是:
2015-02-26 14:16:33.573xxxx[21638:110325] pointInView
2015-02-26 14:16:33.574xxxx[21638:110325] pointInView
2015-02-26 14:16:33.574xxxx[21638:110325] UIGestureRecognizer - FliterTouch
2015-02-26 14:16:33.668xxxx[21638:110325] UIGestureRecognizer - FliterAction
2015-02-26 14:16:33.669xxxx[21638:110325] SelfViewClick
2015-02-26 14:16:33.669xxxx[21638:110325] ButtonClick
FliterTouch和FliterAction返回NO时,控制的和上面规律一样。FliterTouch为NO时,ButtonClick依然会有(证明结论)
实验3:当doubleclick.cancelsTouchesInView =YES时,点击Button
打出的Log是:
2015-02-26 14:34:17.652xxxx[33318:135136] pointInView
2015-02-26 14:34:17.652xxxx[33318:135136] pointInView
2015-02-26 14:34:17.652xxxx[33318:135136] UIGestureRecognizer - FliterTouch
2015-02-26 14:34:17.755xxxx[33318:135136] ButtonClick
也就是说当手势的cancelsTouchesInView属性为YES时,button的响应会cancel手势的响应。
实验4:没有Button点击UIView时,superView和subView的TouchBegin:withEvent:都会走。
总结:点击UIView的时候TouchBegin:withEvent:才走,UIGestureRecognizer和UITouch代理之间不会相互影响
-------------------------
更新一下:以上实验是父子之间的关系,子view的nextResponder就是父View(nextResponder只能获取,不能设置)
如果两个UIView是平级的,那上层的不响应下层的也不会接到相应通知。(这里详细说一下上层不响应的事)
1.如果上层 UIView的userInteractionEnabled设置为NO那么下层会响应。
如果- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event返回NO那么下层也会响应。
下面说一下父子关系下两个不规则形状View的响应方案:
1.子View的- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event会被调用只要UIEvent事件发生在父View上。(无论子View的userInteractionEnabled设置为什么)
2.View的userInteractionEnabled设置为No的时候 ,View的- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event不会被调用
当然pointInside是在hitTest之后被调用的(其实就是hitTest调用的)。
4.父View可以重写
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
CGPoint subviewP = [self(父View) convertPoint:point toView:self.子View];
return [self.子View pointInside:subviewP withEvent:event];
}
这样就可以只让子View完成响应,而父View的其他部分不作响应,其他部分的响应会传递到下层,交给下层去响应。