How to detect touch on screen in custom UIView? - ios

I want to watch in my UIView subclass for user touches on the screen. Especially there are some additional conditions:
the touch should not be catch by my view (for example, if user taps some button or scrolls something that action should be accepted)
there can be multiple views which are watching for touch and they should not conflict with each other
the approach should be as general as possible (so we can catch taps on tabbar or navigation buttons)
I can suppose to add specific fullscreen view with customized hitTest: method. This view has interface to add/remove delegates for watching for touches. But this method is "hard" in coding terms and I would like to find more elegant and simpler solution.

you can write touchesBegan in that UIView subclass.
Because if it had any subview like button or scrollView, they would be first responders ,and touches on scrollView wont fire touchesBegan of your UIView subclass.
And it wont conflict with other touch listeners unless the listener subView is explicitly passing that touch to your Subclass.

Related

Propagating specific touch event to view underneath

I want to implement a feature similar to this:
View A and View B are all child views of the same parent UIView. View A and View B are sibling views. View A is the same frame size as the parent view. View B is only half of the size and it's above View A. I want to capture swipe events/gestures on View B, but still propagate other events/gestures (e.g. Tap) from View B to View A. So user can still interact with View A (e.g. tap on the button on View A) while View B is only capturing swipe gestures.
I have tried implementing following methods on View B
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
but seems like it's all or nothing approach. as I cannot detect in these methods if the event is a tap or a swipe. And I didn't find any API which can programatically trigger a tap on a UIView (not calling touch related methods).
You should move your rear sibling view to be a subview of the front view as this effective looks the same but makes the UIResponder chain behave correctly. UIGestureRecognizer can then do the rest of the work for you. Specifically it has a property, CancelsTocuhesInViews that you can turn off so it doesn't eat touch events and it has a delegate with methods that can allow you to specify the conditions under which a UIGestureRegonizer should fire. Implement the UIGestureRecognizerDelegate methods that you want to make your logic work. For instance if you want the overlay view to handle a tap only if a bunch of other gestureRecognizers don't handle the tap first then you implement gestureRecognizer(_:shouldRequireFailureOf:) and have it return true for every other gesture recognizer you want to go first; your gesture recognizer will then only fire when all of these other gesture recognizers have failed to handle the tap.
If I understand you correctly, what you want to do is usually done using UIGestureRecognizer objects and its subclasses. You can make one gesture recognizer (i.e. a swipe (or was it pan?) gesture recognizer) depend on another one (one for taps).
You can tell one gesture recognizer to only trigger when another has failed to detect its gesture. I haven't had to do that yet, so can't give you more detail, but I'd look into those classes and see if there's a way to chain them so it handles a swipe, and just does not handle taps. If you don't handle a tap, it should automatically go to any subview that will handle it, I think.

Disable userinteraction or touches event in UIView but still enable for subview

I have UIView like this.
I need to put my finger on that view and drag along on those button just like playing piano. Problem is that if initial touch point is on the main view and if I drag along, touches event for main view is triggered and my buttons touch events are not triggered.
As a result, I put this.
[self setUserInteractionEnabled:NO];
Problem is that it has disabled my buttons and other subviews. I want to totally ignore touch event, user interaction from main view but allow for all those subview. How shall I do?
You can set up a notification event for keyboardWillShow and inside the target function set [self setUserInteractionEnabled:NO]; for the superView and when keyboardWillHide notification re-enable it. For hiding the keyboard you could use the GO Button or to dismiss the keyboard add an invisible UIButton to the remaining part of the Screen when the keyboardWillShow event is called and use it to resign first responder.
Hope this helps.
You should create a subclass of UIView for your main view. It should overwrite - hitTest:withEvent: returning always the nearest view for a key.
An alternative solution without inheritance is giving all keys an invisible border such that their views cover the complete main view but never returning the main view.

UIButton not responding to touches - no scroll view

This is my view hierarchy. Send arrow is not responding immediately on the device, it takes multiple touches to trigger the action. But on the simulator, it works perfectly fine. There are no explicit gesture recognisers added in any view, no scroll views and the super view does not delay touch events or anything that I'e noticed in similar questions.
EDIT: Action added through the storyboard. I tried for all touch events and for all of them, the touch is non responsive. Only after a few touches, the action is triggered.
Here's the view debug hierarchy.
Is there any reason why the touch trigger is blocked here? I'm stymied. Help?!
Google Maps override the touches of Views.
Use this way to add your Views.
[self.view insertSubview:viewToAdd aboveSubview:mapView_];
If You adding Views for XIB then Send you map view to back.
[mapView_ sendSubviewToBack:YourView];

Generic way to detect a touch outside UIView frame

I have UIViewController with a custom UIView inside (lets call them VC and button). When button is touched, it's bounds and center changes with animation (it becomes bigger and presents a few options to choose from, after choice it resizes back). I would like to know how to "detect" (and dismiss the default action of that touch) a touch outside of the button (just to "hide" the button, in particular to make button resize to default smaller size).
Is there any generic way I could do that? VC has a lot of objects inside its view (table views, buttons, text fields, custom charts made with quartzcore, etc), do i need to block "interactivity" on all of those elements during the "big mode" of button?
You could subclass what ever view you are using and expand the coordinates that will correspond to a touch in the view by implementing
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
Read more in the docs
http://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instm/UIView/hitTest:withEvent:
This way of implementing it is suggested in some WWDC videos from last year
Add a UIButton having the frame CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height) as the first subview to your mainview (self.view) , add a selector to this button (#selector(backgroundTap)) , now add all other subviews like UITableView , UIButton , etc (as per your requirment) . Now whenever you will click on to the blank space where no Subview is present the backgroundTap selector will be called.

iOS: Several Touch Event on View Controller?

I have developped a small application with 2 View .
My first UIView is a Menu containing some images. When I click on one of them, I switch on the Second UIView to display it.
Afterwards, I created a new UIView who is a "menu extension" of my first Menu. I created a UIView but when I put the component "Swipe", the application do not switch to my second new menu.
I would like to know, if Iphone App supports several touch event on the UIView ?
Objects of class UIGestureRecognizer are attached to a UIView object, not to UIViewController objects. And it is possible to attach multiple gesture recognizers to a single view, see its gestureRecognizers property.
But you have to be careful: If you want a swipe to be recognized, a single tap recognizer might fire before the swipe could be recognized, since the latter requires the move of the finger. Therefore, you can configure multiple gesture recognizers of the same view such that they show the required behavior, e.g. that a single tap recognizer fires only when a swipe recognizer does not fire, etc., see the docs of UIGestureRecognizer Class Reference.

Resources