在我们点击屏幕的时候,iphone OS获取到了用户进行了“单击”这一行为,操作系统把包含这些点击事件的信息包装成UITouch和UIEvent形式的实例,然后找到当前运行的程序,逐级寻找能够响应这个事件的对象,直到没有响应者响应。这一寻找的过程,被称作事件的响应链。
在iOS中,能够响应事件的对象都是UIResponder的子类对象。UIResponder提供了四个用户点击的回调方法,分别对应用户点击开始、移动、点击结束以及取消点击,其中只有在程序强制退出或者来电时,取消点击事件才会调用。那么为什么继承自UIResponder的类就能够接收并处理事件呢?
1.第一响应者
栈顶的响应者作为最优先处理事件的对象也就是(第一响应者),假设AView不处理事件,那么出栈,移交给UIView,以此下去,直到事件得到了处理或者到达AppDelegate后依旧未响应,事件被摒弃为止。通过这个机制我们也可以看到controller是响应者栈中的例外,即便没有pointInSide: withEvent:的方法返回可响应,controller依旧能够入栈成为UIView的下一个响应者。
如果当前这个view是控制器的view,则控制器是父控件,如果view不是属于控制器的view,则父控件就是上一个响应者。
2.事件的传递(这是一个过程过程过程)
触摸事件对象由上往下传递(从父控件传递到子控件),最终找到最适合的控件来处理这个事情,如果找不到则将其丢弃。就是UIApplication->window->寻找处理事件最合适的view。
如果父控件不能接受触摸事件,那么子控件就不可能接收到触摸事件。
补充:UIView不能接收触摸事件的三种情况:
不允许交互:userInteractionEnabled = NO
隐藏:如果把父控件隐藏,那么子控件也会隐藏,隐藏的控件不能接受事件。(hidden = YES)
透明度:如果设置一个控件的透明度<0.01,会直接影响子控件的透明度。alpha:0.0~0.01为透明。
例如,不想让蓝色的view接收事件,那么可以设置蓝色的view的userInteractionEnabled = NO;那么点击黄色的view或者蓝色的view所产生的事件,最终会由橙色的view处理,橙色的view就会成为最合适的view。
所以,不管视图能不能处理事件,只要点击了视图就都会产生事件,关键在于该事件最终是由谁来处理!
也就是说,如果蓝色视图不能处理事件,点击蓝色视图产生的触摸事件不会由被点击的视图(蓝色视图)处理!
注意:如果设置父控件的透明度或者hidden,会直接影响到子控件的透明度和hidden。如果父控件的透明度为0或者hidden = YES,那么子控件也是不可见的!
网友评论