手势识别状态机
Interacting with Other Gesture Recognizers
When a view has multiple gesture recognizers attached to it, you may want to alter how the competing gesture recognizers receive and analyze touch events. By default, there is no set order for which gesture recognizers receive a touch first, and for this reason touches can be passed to gesture recognizers in a different order each time. You can override this default behavior to:
- Specify that one gesture recognizer should analyze a touch before another gesture recognizer.
- Allow two gesture recognizers to operate simultaneously.
Prevent a gesture recognizer from analyzing a touch. - Use the UIGestureRecognizer class methods, delegate methods, and methods overridden by subclasses to effect these behaviors.
手势冲突,同一个touch被手势识别的顺序可能不一样
Declaring a Specific Order for Two Gesture Recognizers
例子:拖动手势与swipe手势冲突,可以设置
If the swipe gesture recognizer determines that a touch is a swipe, the pan gesture recognizer never needs to analyze the touch. If the swipe gesture recognizer determines that the touch is not a swipe, it moves to the Failed state and the pan gesture recognizer should begin analyzing the touch event.
to set up a permanent relationship between the two objects at creation time,同view层级的
- requireGestureRecognizerToFail:
下面两个代理方法,that you can set up failure requirements between recognizers in different view hierarchies.跨view层级,用途还看不太懂。。。
- gestureRecognizer:shouldRequireFailureOfGestureRecognizer:
- gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:
如果想单击和双击共存,单击会有一个延迟直到双击的recognize变成失败状态
Preventing Gesture Recognizers from Analyzing Touches
protocol to stop
- gestureRecognizer:shouldReceiveTouch:
- gestureRecognizerShouldBegin:
Permitting Simultaneous Gesture Recognition
两个手势同时起作用
- gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
Interacting with Other User Interface Controls
对于重叠的系统UIControl子类控件,如一个button在一个tap recognizer的上方重叠一起,用户按button的时候只会响应button,不会响应recognizer
Gesture Recognizers Interpret Raw Touch Events
An App Receives Touches in the Touch-Handling Methods
- touchesBegan:withEvent: method when one or more fingers touch down on the screen.
- touchesMoved:withEvent: method when one or more fingers move.
- touchesEnded:withEvent: method when one or more fingers lift up from the screen.
- touchesCancelled:withEvent: method when the touch sequence is canceled by a system event, such as an incoming phone call.
Regulating the Delivery of Touches to Views
A window delays the delivery of touch objects to the view so that the gesture recognizer can analyze the touch first.
During the delay, if the gesture recognizer recognizes a touch gesture, then the windownever(回头再看看这里)
delivers the touch object to the view, and also cancels any touch objects it previously sent to the view that were part of that recognized sequence.
touch发生
=>touchObject=>UIApplication=>UIWindow=>send Touch To gesture recognizers =>view
试验,测试UIView的响应链方法和gesture的方法顺序
-
tap
2. panGesture
一开始是调用UIView的事件,后面被识别为pangesture后只执行手势的回调方法
开启
gesture.delaysTouchesBegan = true;
后,UIView方法完全不执行,但单点击一下松手后如下图Affecting the Delivery of Touches to Views
这里看的迷迷糊糊的
涉及属性
- delaysTouchesBegan
- delaysTouchesEnded
- ignoreTouch:forEvent:
Creating a Custom Gesture Recognizer
Event Delivery: The Responder Chain
When a user-generated event occurs, UIKit creates an event object containing the information needed to process the event. Then it places the event object in the
active app’s event queue
. For touch events, that object is a set of touches packaged in a UIEvent object.
Touch events. For touch events, the window object first tries to deliver the event to the view where the touch occurred. That view is known as the hit-test view. The process of finding the hit-test view is called hit-testing
Motion and remote control events. With these events, the window object sends the shaking-motion or remote control event to the first responder for handling.
Hit-Testing Returns the View Where a Touch Occurred
- hitTest:withEvent:
- pointInside:withEvent:(传入的point与view的bounds比较,如果在bounds范围内则返回true,如果返回false,上面的hitTest:withEvent:返回nil)
The hitTest:withEvent: method returns the hit test view for a given CGPoint and UIEvent. The hitTest:withEvent: method begins by calling the pointInside:withEvent: method on itself. If the point passed into hitTest:withEvent: is inside the bounds of the view, pointInside:withEvent: returns YES. Then, the method recursively calls hitTest:withEvent: on every subview that returns YES.
If the point passed into hitTest:withEvent: is not inside the bounds of the view, the first call to the pointInside:withEvent: method returns NO, the point is ignored, and hitTest:withEvent: returns nil. If a subview returns NO, that whole branch of the view hierarchy is ignored, because if the touch did not occur in that subview, it also did not occur in any of that subview’s subviews. This means that any point in a subview that is outside of its superview can’t receive touch events because the touch point has to be within the bounds of the superview and the subview. This can occur if the subview’s clipsToBounds property is set to NO.
The Responder Chain Is Made Up of Responder Objects
The UIResponder class is the base class for all responder objects,如 UIApplication, UIViewController, and UIView
An object becomes the first responder by doing two things:
- Overriding the canBecomeFirstResponder method to return YES.
- Receiving a becomeFirstResponder message. If necessary, an object can send itself this message.