功能需求:当button超出父控件frame的时候如何与用户交互
如图:btn1和btn2都是蓝色View的子控件,但是他们超出了蓝色View的frame
如果不做任何处理,点击btn,btn是不能与用户交互的
Btn3在父控件范围内,可以与用户交互
这里是源码
响应者链条:(系统如何找到最合适的View来响应用户的交互)
当用户点击屏幕
产生一个点击事件交给UIAppliction
UIAppliction交给UIWiondw
UIWiondw问控制器View:触点在不在你身上?
在,则把点击事件交给控制器View
控制器View问自己的子控件(从最后添加的,也就是最上层的view开始询问):触点在不在你身上?
在,则把事件传递给这个子View
不在,则继续问下一个子控件
如果找到了合适的子控件,则把事件传递给子控件(子控件继续询问自己的子控件来查找更合适的view)
如果没有找到,则自己处理事件
例如点击了Btn3:
UIWiondw问控制器的白色View触点在你身上吗?
在,事件传递到控制器的白色View上
白色Viwe问蓝色Viwe,触点在你身上吗?
在,事件传递到蓝色View
然后蓝色View问Btn3,触点在你身上吗?
在,则事件交给Btn3
Btn3已经没有子控件(也就是没有更合适的View了)
Btn3处理了点击事件
又例如点击了Btn1
UIWiondw问控制器的白色View触点在你身上吗?
在,事件传递到控制器的白色View上
白色Viwe问蓝色Viwe,触点在你身上吗?
不在,则白色View处理点击事件(因为白色View已经没有其他子控件可以询问,Btn1是蓝色Viwe的子控件)
所以Btn1不能响应用户的交互
如何让Btn1与用户交互
在询问子View的时候,系统是通过这个方法来寻找最合适的View:
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
所以我们可以重写控制器View的这个方法,来按照自己制定的规则来寻找最合适的View:
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
//当前触点坐标系是控制器的view
//转换成btn1的坐标系
CGPoint btnP = [self convertPoint:point toView:self.btn1];
if ([self.btn1pointInside:btnP withEvent:event]) {//判断点击点是否在btn1上
//如果点击点在btn1上 那么就让btn1来处理事件
return self.btn1;
}else{
//如果不在btn1上 就按照系统默认做法 寻找合适的view来处理事件
return [super hitTest:point withEvent:event]
}
}
这样的话,当触点在Btn1上的时候,这个方法就会返回Btn1
那么系统就会把Btn1当做最合适的View来处理事件
感谢阅读
你的支持是我写作的唯一动力
网友评论