I have a 5 components UIPickerView which needs to be disabled to normal user interaction (ie: no spinning / clicking around to spin them). I need however to detect touches inside them and react according to which component was pressed.
I tried UIGestureRecognizer and UITapGestureRecognizer with cancelsTouchesInView set to YES: It fires up and blocks the single taps but not the dragging around. I tried didSelectRow:inComponent but it's only firing up when the pickers spinned which is a behavior I don't want.. the reels must never spin on a user interaction as mentioned above.
Solved this by adding a UIGestureRecognizer to the background image (with user interaction enabled) and looking at the locations of the taps to determine if the taps were within the region of a UIPickerView component.
Related
Example 1:
When invoking 3D Touch on app icon, you are able to make selections without lifting the finger up.
Example 2
Long pressing on a keyboard key allowing you to drag in to different selections without lifting finger up.
If the app icon is the first view and the pop up is the second view, how can I transfer touch down from first to second view?
Normally, a view loses control of the touches when the fingers leave its area. But if you set isMultipleTouchEnabled to true, it will keep control over touches if the finger leave its area. If you use a button or another UIControl you can assign actions to touchDragExit, touchUpOutside or touchDragOutside etc. to handle events outside of the control.
How does the UIActionSheet's hit detection work? When a user selects an option and then moves it's finger to another option, the other option is highlighted as seen in the GIF's below. The detection also knows when a user is scrolling.
So this is achieved by listening for multiple UIControlEvents. Chances are you're used to listening for touchUpInside as this is standard for UIButton behaviour. But there are plenty more besides that. A full list and documentation can be found here.
In your case, you want to listen to touchDragEnter and touchDownInside, making the callback from these invoke some code that changes the background colour of your button.
You should also listen for touchDragExit and touchUpInside to return the background colour to normal.
Additionally, you should run the action code in touchUpInside.
I hope this clears things up!
UIAlertController contains a stack of items in subview with type UIStackView, this stack view is placed on the view with type _UIInterfaceActionRepresentationsSequenceView that has three gesture recognizers with types:
• UIScrollViewDelayedTouchesBeganGestureRecognizer
• UIScrollViewPanGestureRecognizer
• _UIDragAutoScrollGestureRecognizer
You can inspect it with Xcode built-in tool: User Interface Inspector.
I think that custom handlers of these recognisers provide this drag-and-highlight function.
Internal logic of UIAlertController handle touches and hit test subview in stack and set highlighted boolean property to YES for item under user's finger and to NO for others.
I have a view set up as a game controller for an UIImageView on my screen. I have two directional arrows left/right, and an A and B button.
When the user holds a directional (touch down) it moves the player, and on the touch Up method it stops.
However, while holding a directional UIButton, the other UIButtons will not function until you release the touch Up on the directional, thus delaying the tap.
Also, say if you held the A button down and simply tap a directional once, the A button will register the directional button being touched down instead of A, even though A will be in its highlighted state.
I have checked the connections for everything, they are all separate UIButton instances with only those actions linked.
It seems that a touchUp method is being passed to another UIButton instance making two presses at the same time impossible. I have not had issues with this before.
Any help would be appreciated thank you.
Check that multipleTouchEnabled is true for parent views:
multipleTouchEnabled
A Boolean value that indicates whether the receiver handles
multi-touch events.
And that exclusiveTouch is false for buttons:
exclusiveTouch
A Boolean value that indicates whether the receiver handles touch
events exclusively.
This is a pretty hypothetical question just to understand proper design but lets say I have two custom UIViews.
One of them is essentially a container that I'll call a drawer. Its purpose is to hide and show content. It's a lot like the notification center on iOS where you swipe to pull it open and flick it back up to close it. It's a generic container than can contain any other UIView. It has a UIPanGestureRecognizer to track the finger that's pulling it open/closed. It might also have a UISwipeGestureRecognizer to detect a "flick".
The other view is a custom map widget that has UIPan/Rotation/Pinch GestureRecognizers.
I think the drawer view should be the UIGestureRecognizerDelegate for the Pan/Swipe GestureRecognizers so that it can prevent touches from being delivered unless the user is grabbing "the handle".
My first instinct is for the map to be the UIGestureRecognizerDelegate of the pan/rotation/pinch gestures so that it can allow them to all run simultaneously.
The problem I'm having is that, I really don't want the map to receive any touches or begin recognizing gestures until the drawer is completely open. I'd like to be able to enforce this behavior automatically in the drawer itself so that it works for all subviews right out of the box.
The only way that I can think to do this is to wire all of the gestures handlers to the ViewController and let it do everything, but to me that breaks encapsulation as now it has to know that the map gestures need to run simultaneously, that the drawer should only get touches on it's handle and that the map should only get touches when it's open.
What are some ways of doing this where the logic can stay in the Views where I think it belongs?
I would do something like this to make the subviews of the drawer disabled while panning. Essentially loop through the drawer's subviews and disbale interaction on them.
[self.subviews enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop){
subview.userInteractionEnabled = NO;
}];
And something similar again for when you want to re-enable user interaction on the subviews.
This should already Just Work™. A gesture recogniser is attached to a view; when a continuous gesture is recognised, all subsequent touches associated with that gesture are associated with that view.
So in your case, when the drawer pan is recognised, no touches associated with that pan should ever cause behaviour in your map view's pan/pinch/rotation gestures (unless you explicitly specify that they should using the appropriate delegate methods).
Or do you mean that you want to prevent the user from, halfway through opening the drawer, using another finger (i.e. another gesture) to start scrolling the (half-visible) map? If so, you should just set userInteractionEnabled on the drawer's contentView (or equivalent) to NO at UIGestureRecognizerStateBegan/Changed and YES again at UIGestureRecognizerStateEnded/Cancelled.
I am trying to programmatically make a 2nd tap occur on the screen a few seconds after the actual tap event occurs. For example, if I tap the screen in the bottom left corner...is it possible to then programatically make a tap occur at a specified set of coordinates a few seconds later (see image).
You don't need to do horrid things like overlaying invisible buttons and faking taps.
All you need to do is set your view controller to conform to the UIWebViewDelegate protocol, and implement the webView:shouldStartLoadWithRequest:navigationType: protocol method.
By implementing this method and checking for a link-tap event with if(navigationType == UIWebViewNavigationTypeLinkClicked) your app is now being informed of link-taps without intercepting and eating them via invisible buttons, so your web site doesn't miss out on being informed of the request.
You can then implement the necessary logic to change categories in JQuery on the site.