UIScrollView: override the addition of pan/pinch gesture recognizers - ios

I want to make a custom UITextView that functions exactly like the standard text view but extends just a UIView without any gesture recognizers . Since a UIScrollView is basically a UIView with added gesture recognizers I figured this is just a matter of overriding the method of UITextView, inherited from UIScrollView, in which the view has gesture recognizers added to it. Does anyone know which methods these are so my custom text view can skip adding a pan and pinch gesture recognizer altogether? Right now, I have my custom textview remove all of its gesture recognizers upon initialization which seems icky on the performance end.

Related

Zooming on content view inside of scrollview doesn't work

I'm creating a scrollview with content view inside of it. inside of the content view there are buttons.
from this point, i already can zoom and pan on content view. but when the touch happen on a button the scrollview doesn't zoom.
I have just had the same problem and solved it with the following steps :
Create a UIView.
Create a UITapGestureRecognizer
Add the UITapGestureRecognizer to the UIView to handle taps.
Create a UIButton.
Disable User Interaction (isUserInteractionEnabled = false) on the button.
Add the UIButton as a SubView of the UIView.
In the UITapGestureRecognizer tapped selector, handle the UIButton touchesUpInside call.
Add the first UIView into the UIScrollView.
Make sure the UIScrollView delay content touches delaysContentTouches = true
The UIScrollView should be able to now seamlessly zoom and you can respond to your buttons.
You can skip the button altogether if you want and just handle the Tap in the Gesture Recognizer. I had to do it the way above because the buttons were a custom sub classed buttons and had a lot of additional custom rendering and functionality included.

Movable UIButtons

Scenario:
There is an UIView as a sub view of a UIScrollView and there is a UIImageView as a sub view of the UIView.
Requirement:
When the user touches on the UIImageView I want to add a UIButton as a sub view at that touch point. Any amount of UIButtons could be added (Within the UIImageView frame). These UIButtons should also be movable inside the UIImageView frame.
What I have done
I have sub classed the UIView and I'm detecting touches using methods touchesBegan, touchesMoved, touchesEnded and adding UIButtons. UIButtons are added with UIGestureRecognizers with a method implemented to the pan gesture.
Problem
When I add more than one button the earlier ones becomes non-movable and doesn't even recognise touch up inside.
Thank you all for the help. I ended up doing this https://github.com/Tulakshana/TTaggableView
You should read about Gesture Recognizers:
https://developer.apple.com/library/ios/documentation/uikit/reference/UIGestureRecognizer_Class/Reference/Reference.html
http://www.raywenderlich.com/6567/uigesturerecognizer-tutorial-in-ios-5-pinches-pans-and-more
Start with UITapGestureRecognizer for showing UIButtons.

make superview respond to subView's UIPanGesture in some cases

I have a scrollView and it contains a subView. SubView has a panGesture added to it.
What I want:
I need pangesture to work on subview only if the panning is done vertically. If the panning happens horizontally, I want the scrollView to respond for the panning instead of subview. How can I acheive this
Note: Iam able to find programatically when the panning happens horizontally.
There are several ways to do this:
Depending on what your subview does, you maybe able to replace it with a scrollview and lock it to scroll only vertically. (while the super should scroll only horizontally).
You can try feeding the touch information from the subview to it's superview if the pan gesture is moving horizontally. You could do this using a delegate pattern or, if you know what you're superview is, just access superview in your subview. However, this creates a strong coupling between the two views and probably shouldn't be done. It would be fragile and many would consider it code smell.
(best option) - Subclass UIGestureRecognizer and create your own gesture recognizer that only recognizes vertical movement. Use that instead of the UIPanGestureRecognizer.
Option 3 is the best, but probably the most work. You'll want to read Apple's docs on subclassing UIGestureRecognizer: Apple Docs - UIGestureRecognizer.
I've also written my own drag gesture recognizer, FlxDragGestureRecognizer.m, FlxDragGestureRecognizer.h (similar to a pan gesture recognizer), which you can use if you'd like, or take a look at to get a good idea of how to subclass UIGestureRecognizer. You can use this class to recognize touches moving only in certain directions, otherwise it will fail (which will allow other gesture recognizer to recognizer, like the scrollview). It also has a lot of other customizations and information it gathers, like velocity.
Since you already know how to detect the panning, then in you will need to implement a delegate protocol in your superview, a delegate property in your subview and assign your superview as a delegate for your subview.
when detecting horizontal panning, call the delegate method, when detecting vertical panning, implement what you want in the subview.

UIPanGestureRecognizer requireGestureRecognizerToFail delays UIScrollView

i have a UIPanGestureRecognizer on my rootViewControllers view
that controls only 2 finger swipe ( min and max are set on 2 )
I have a couple of UITableView and UIScrollView on my rootViewControllers view.
But the 2 finger swipe should always have number 1 priority
so i put a requireGestureRecognizerToFail on my UITableView and UIScrollView's panGesture property.
this works perfectly but now when i pan my UITableView and UIScrollView, it doesn't move until i stop swiping.
Is there a solution for this?
i have added a sample project to display what the problem is: https://github.com/avalanched/UIScrollViewTest
You will need to allow the gesture recognizers to simultaneously recognize by setting the delegate on all the gesture recognizers and implementing gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:.
See Apple's UIGestureRecognizerDelegate Documentation.
You also need to remove the requireGestureRecognizerToFail calls, these are what causes the delay.

Can I pass a pinch gesture recognizer to a ScrollView to have it zoom?

I wrote a custom pinch gesture recognizer for my ScrollView's zooming, and I handle pinch touches in a method in my view controller.
But in some cases, I want the ScrollView to behave exactly as it would normally behave (if it used the standard pinch gesture recognizer that comes with ScrollView).
Is there some way that in such cases I can pass my custom gesture recognizer to the ScrollView and it would use that recognizer to scale the view as it normally would?
Could I pass the gesture recognizer to the selector that is triggered by pinch actions?
I have not tried this, but here's an idea:
When you set your own gestureRecognizer, store the ScrollView's pinchGestureRecognizer in an iVar. You should then be able to dynamically exchange your gestureRecognizer and the original one.
As of iOS 5 UIScrollView exposes a pinchGestureRecognizer property, but this is read-only. To get it to use your own instead you have to subclass UIScrollView and overwrite this property hoping that internally UIScrollView also uses this property to get the gesture recognizer to add when zooming is enabled.
However it is quite dangerous messing with scroll view's gesture recognizers, especially to modify their behavior. Even just having a different delegate will trigger an exception. So proceed at your own risk.

Resources