iOS Swift 4: UIView in UIScrollView - ios

I have a UIImageView with a tap gesture recognizer as a subview of a UIScrollView.
A.) If the UIImageView isUserInteractionEnabled=false the scroll view works fine (pinch zoom, scroll) but doesn't recognize the tap gesture on the image.
B.) If isUserInteractionEnabled=true I cannot start pinch zoom or scroll from the image but the tap gesture works.
How can I manage it to work (keep scrolling and zooming but recognize tap on content)?

Because UIScrollView has gestures within for handling scroll, pinch, it means when your UIImageView.isUserInteractionEnabled = true, the UIImageView' tap gesture take those touches and do not forward it to UISCrollView.
Here is the solution by implementing a UIGesture's delegate method: https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/coordinating_multiple_gesture_recognizers/allowing_the_simultaneous_recognition_of_multiple_gestures

Related

Swipe down scroll view to dismiss view controller

I use a ImageScrollView from here, which is basically a UIScrollView to allow pinch to zoom into a picture. I now wanted to add the possibility to swipe down the picture to dismiss the view controller. I created a UIPanGestureRecognizer and it works fine if zoom scale is at the minimum value (so the whole picture is visible without zoom). But how can I skip the pan gesture recognizer if the zoom scale is above the minimum value? Because it lays on top of the ImageScrollView, I can't scroll in the picture because scrolling gesture is fetched by the UIPanGestureRecognizer. Any idea how to solve this?
For show image like whatsApp imageView functionality you go with the apple framework QuikLook. It will automatically handle Zoom, Dismiss the image while Swipe etc.
It also support for the documents. It will reduce your effort a lot
It's too easy to handle this operation by adding a trigger on swipe action (gesture calling method).
When zoomScale > minimumValue; set returnstatement
A simple example with Swift 4:
let zoomScale: 1.0
let minimumValue: 0.5
func handlePanGesture(gesture: UIPanGestureRecognizer) {
if (#<set pan gesture down moving condition>#) {
if (zoomScale > minumumValue) {
return
}
}
// perform your next operations
}

Moving view but keeping imageview in fixed position

I'm moving a UIView up with a swipe, but I want the imageView within the UIView to stay in its position. I got this working by placing my imageView under a separate UIView ( I needed to include a label under the imageview) by doing [self.view insertSubview:self.imageViewHolder aboveSubview:self.panedView];. The problem now is that when i swipe down over the imageView, my view that I swiped up won't come back down unless I swipe around the imageView. This is because the UIGestureRecognizer is associated with the view under the imageView. Any simple ways around this?
Gesture recognizer code:
UISwipeGestureRecognizer * swipeUpRec = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleUpSwipe:)];
[self.panedView addGestureRecognizer:swipeUpRec];
[self.imageViewHolder addGestureRecognizer:swipeUpRec];

How to conditionally "pass through" a gesture from a UIButton to a UIScrollView?

I have a long, horizontal, narrow UIScrollView containing several buttons side-by-side. When a user drags a button vertically, a specific method is triggered (via a UIPanGestureRecognizer), and the scrollview doesn't scroll (even if his/her drag begins to go left or right). This is all good.
When a user drags horizontally anywhere on the scrollview, including directly on a button, the UIPanGestureRecognizer ignores the effect and the scrollview should scroll. It's the last effect I'm having trouble with: when the user horizontally drags directly on a button, the scrollview doesn't scroll. How can I "pass through" that horizontal gesture to the scrollview?
Thanks for reading!
Add this method to your buttons' UIPanGestureRecognizer's delegate:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return (otherGestureRecognizer == _scrollView.panGestureRecognizer);
}
On UIScrollView you can override
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
Subclass UIScrollView (or UITableView) and return YES. It will cancel any touch from subviews when scrolling starts.
Give a thought to UILongPressGestureRecognizer. This might help you: Combine longpress gesture and drag gesture together

ScrollView - Send Touches to View below

My setup - and I cannot change it - is right now:
Root View
- UIView
-- ScrollView2
- ScrollView1 (this is top in view hierarchy)
The first scrollview is used to apply some transitions on the below UIView. The second scrollviews contentoffset (captures in scrollViewDidScroll:) is used to apply other animations.
Question: How can I transfer/delegate all touches from ScrollView1 to ScrollView2? Please note that the ScrollView1 is on top of everything and the others views are below of it - not subviews!
You can add the pan gesture recogniser from a scroll view to any other view you want and this will effectively delegate the touches from the targeted view to the scroll view. You can also add the pinch gesture recogniser if you want to control zoom.

How to implement UITableView like scrolling and cell tapping behavior?

In UITableView, you can tap and hold on a table cell and cancels the tap and continue on with scrolling if you move your finger. How can this done with UIScrollView with a subview? I am able to make it so you can scroll and you can tap on the subview, but am having issue with the latter behavior - make scrollview continue to scroll if you move your finger while tapping and holding.
I assume you are using a UITapGestureRecognizer on the subview. The scroll view uses a UIPanGestureRecognizer for scrolling. You simply need to tell the tap recognizer not to recognize unless the pan recognizer fails.
If you are targetting iOS 5, this is very easy:
[self.tapRecognizer requireGestureRecognizerToFail:self.scrollView.panGestureRecognizer];
If you are targetting an older version of iOS, older versions of UIScrollView don't have the panGestureRecognizer property. Instead you have to search through the scroll view's gestureRecognizers array:
for (UIGestureRecognizer *recognizer in self.scrollView.gestureRecognizers) {
if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]])
[self.tapRecognizer requireGestureRecognizerToFail:recognizer];
}

Resources