handling same touch event with multiple control (parent and child) - iphone

I need to handle a touch event on my custom uiviewcotroller. I have a sub controller within the view that already handle touch event (it's a plot that handle zooming and scrolling).
I want to make a tabbar disappear when I tap the screen once. Actually it only works (even tought the tabbar doesn fade away but simply is no visible) in the areas in which the subcontrol is not present but I need it to work everywhere still handling the subcontrol events.

Make sure you're calling the superclass's event handler method in your event handler method to continue propagation of the event up the responder chain.
Also make sure the subcontrol's exclusiveTouch property is set to NO.
You might want to have a look at the event handling documentation.

Try to set userInteractionEnabled = NO in subcontrol view.
UPD: Try to add transparent button to subcontrol.

Related

How do you disable touch to screen without using beginIgnoringInteractionEvents?

from a similar question/answer
You could always put a transparent UIView over top of the area you
want to "disable" tap input for, have it listen for taps, and have it
ignore them. Remove the UIView (or hide it) when you want input to be
listened to again.
Now, I can understand the strategy, but would someone enlighten me with a code?
How do you make a view
1. listen for taps
2. have it ignore them
Would it not pass touch to views behind it?
Set a plain UIView's userInteractionEnabled property to YES, but don't have any code in there to respond to touch events. The view will then 'swallow' all touches.

Custom MKAnnotationView - How to capture touches and NOT dismiss the callout?

I have a custom MKAnnotationView subclass. It is showing the view exactly as I want it to. In that view, I have a button. I want to capture events on the button to perform an action. This works just fine.
However, I do NOT want the callout to be dismissed or disappear. Basically, touching the button in the callout will start playing a sound, but I want to leave the annotation up so the user can press stop if they want to, without having to touch the map pin again to bring the annotation back up. In another instance, I want the button touch to animate more details in the callout, so I definitely don't want to dismiss the callout at that point.
How can I keep the callout from disappearing whenever the user selects the callout or a button inside the callout?
This may not be the best solution, but it definitely works. First off, I tried a number of things, like observing for context and such, but I never got past crashing, and it seemed cumbersome. So, this is what I did:
I first specified what the controlling factor was for keeping an alert viewable. In my case, I created a custom annotation view, and whenever the user clicks a button on that custom view, I want it to stay visible, and maybe even change the content. So, I set a delegate on that custom view so that my map can know when something changes. In my map view controller, I catch that message and set a class member variable to true to signify that I want the annotation view to stay.
NOTE: This will happen before the selection messages occur.
Now, in my didDeselectAnnotation method, I check the boolean value. If I want to keep it visible, I opt to NOT remove my annotation, I reset the boolean value, and I re-select the annotation manually, setting animation to NO. This lets the annotation view "stay" visible--maybe a cheat, but the user can't see the difference. Whenever that boolean value says that deselection is ok, I simply remove the annotation and all is well.
So, the workflow is this:
Touch pin
CustomAnnotationView is displayed
User clicks a button on CustomAnnotationView, which notifies the delegate (mapView) that the
action occurred
Set the class boolean value to know that you want to keep the annotation around
mapView then calls didDeselectAnnotation method
In didDeselectAnnotation method, use conditional to decide if you should remove the annotation, or keep it around by not removing the annotation and manually re-selecting it without animation.
I hope this helps others. It took me a while to figure this out, so I hope it saves you time.
If you find a better solution, by all means, please post it here!
you can suppress callout closing by using hittest, check this following post.
Detect tap on title of callout

How to disable multitouch when having several views?

I created my own custom view that extends UIControl. This custom view has its own touch implementation. I implemented touchesBegan, Moved, Ended, and Canceled methods in it.
In the main view controller, I created several instances of this view. So in the screen, there are a number of custom buttons.
I want to disable multitouch in my app. If I click one custom button, then other buttons shouldn't respond.
Actually, it was easy to implement this. While I held some buttons, I could just make other buttons' userInteractionEnabled property to NO until I ended touch.
But the problem is that when I tap these several buttons at the same time, two or more touchesBegan methods work simultaneously, and message passing is messed up.
I tried to set multiTouchEnabled = NO and exclusiveTouch = YES, but it still didn't work.
How can I force to disable multitouch in my app?
Thank you.
You need to set exclusiveTouch to YES, not NO (which is the default anyways). The name of the property refers to the view being the exclusive recipient of any touch events for the duration.

Propagating touches from UIApplication in a custom manner

Is it possible to propagate touches from shared application object to a custom view which has not actually received touches and somewhere at the back of the top view? Assume that I can't use my top view to track touches.
It would be difficult - because the top view receives the event first.
You can't just call userInterActionEnabled on the top view, and pass the event down to a lower layer?
Why can you not use the top view to track touches?
If the top view is a subclass then you can use the touchesBegan: method. To pass this onto another subclass you could just use NSNotificationCenter, passing the set of touches as the object. If you're unfamiliar with this you can check out my explanation on this post:
Hittest event problem

Best way to implement tap anywhere to cancel (a la App Store download button)?

I have a UI element. When I tap it, it animates to an intermediary state. A tap anywhere else on the screen should cancel the interaction, while another tap on the UI element should proceed.
I've implemented this using a guard view (subview of window & above every other subview) and then reparenting the element into the guard view before the animation, but I'm curious as to what other ways people can think of doing this, that might be cleaner.
I've thought of using a guard window instead of a view, and messing with hitTest:withEvent: and pointInside:forEvent:. The problem with those two is that the superview of the element does not take up the whole screen.
This sounds like a perfect use case for what exclusiveTouch sounds like (all touch events anywhere go to that view), but in reality isn't (all touch events started in that view only go to that view, and not other views at the same time).
Thoughts?
You can create another UIWindow, call -makeKeyAndVisible and then destroy the window when you're done with it. UIAlertView does exactly this to take control of the entire screen.
I've written some code that achieves this behavior fairly cleanly. You don't need to reparent the element into the guard view. You just need a UIControl subclass that can pass touches through to the element. You also don't need to destroy the guard window; you can just hide it. Your UIApplicationDelegate can listen for UIWindowDidBecomeHiddenNotifications that are sent by UIWindows that aren't the main window, and then call the main window's -makeKeyAndVisible method.
A much simpler solution I came up with is to create another UIButton within the store button you're creating and then insert it below self in the keyWindow of the application. Then use that buttons UIEventTouchDown to cancel the selection of the store button and remove itself. Works like a charm.