Reputation: 3508
I want to achieve the following.
Scenario: The iOS keyboard is on-screen while the user is typing into a particular text field. The user can tap anywhere outside of the keyboard and text field to dismiss the keyboard (without activating any buttons which are visible). Also, the user can drag outside of the keyboard and observe the normal drag behavior on some arrangement of scrollable views.
Conceptually, I’m placing a “cover” UIView
over most of the screen which behaves such that:
If the user taps on the cover, then I capture that tap (so that I can, e.g., dismiss the keyboard). This is easy to achieve by intercepting touch events in a UIView
subclass or using a tap gesture recognizer.
If the user drags on the cover, then the cover ignores or forwards these touches; these are received by the layers underneath just as they would have been without a cover.
So: the user should be able to scroll content underneath the cover, but not tap content underneath the cover. A tap “outside” of the keyboard and text field should dismiss the keyboard (and cover), but should not activate anything.
How can I achieve this?
Upvotes: 9
Views: 7331
Reputation: 1870
A custom view which forwards all touches it receives:
class CustomView: UIView {
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
var hitView = super.hitTest(point, withEvent: event)
if hitView == self {
return nil
}
return hitView
}
}
From there you can go different ways to just make use of tap gestures. Either observe the UIEvent for its touches, or use a gesture recognizer.
Upvotes: 1
Reputation: 1276
Add the tap gesture the usual way:
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
[self.view addGestureRecognizer:tapGesture];
But what you may be looking for is this :
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Documentation says : This method is called when recognition of a gesture by either gestureRecognizer or otherGestureRecognizer would block the other gesture recognizer from recognizing its gesture. (https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIGestureRecognizerDelegate_Protocol/index.html#//apple_ref/occ/intf/UIGestureRecognizerDelegate)
This way, you may be sure it's totally transparent, and also that nothing will prevent your recognizer from being called.
Upvotes: 2
Reputation: 2344
1: Add a tap gesture recognizer to the view:
//Adding tap gesture
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
tapGesture.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:tapGesture];
2: In handleTapGesture you resignFirstResponder of the keyboard
- (void)handleTapGesture:(UITapGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateRecognized) {
//Resign first responder for keyboard here
}
}
Elaborated a bit on the answer above. UIGestureRecognizerStateRecognized makes sure it's single tab events that gets recognized.
Is this the functionality you where after?
Upvotes: 0