Disable touch on scroll, enable gestures on its subviews? - ios

I have to disable scrolling on scrollview, so it can be scrolled only by software and not by the user.
scrollView.isUserInteractionEnabled = false
This scrollview has some views, and they have TapGesture on them, I enabled their interaction :
view.isUserInteractionEnabled=true
But it will not work unless I enable the interaction on the scroller.
Is there any other way to achieve my goal ?

Don't use isUserInteractionEnabled to disable scroll on your tableView. Use isScrollEnabled instead of isUserInteractionEnabled and you don't need to change anything of your view
scrollView?.isScrollEnabled = false;
If you set isUserInteractionEnabled to false, it will ignore touchs on subviews of tableView, doesn't matter isUserInteractionEnabled of the subview is true or false.

Set isScrollEnabled to false instead of userInteractionEnabled.
scrollView.isScrollEnabled = false
isScrollEnabled
If the value of this property is true , scrolling is enabled, and if
it is false , scrolling is disabled. The default is true. When
scrolling is disabled, the scroll view does not accept touch events;
it forwards them up the responder chain.

Related

Swift: Hide Scrollview header

I would like to hide the header of my scrollview.
I have a scrollview
//Contains everything inside the view
let scrollView = UIScrollView()
scrollView.alwaysBounceVertical = true
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.showsHorizontalScrollIndicator = false
which spans across the whole width and height of my view. When scrolling down, a weird header appears and blocks a bit of the scroll view content. I would like to hide that overlay. The worst thing is, that in bright mode, the overlay is white. That clashes with my colors. How do I go about removing it?
The overlay is the navigation bar - it appears as soon as you scroll. To hide it completely, you can set navigationController?.setNavigationBarHidden(true, animated: false). Or, you can pass in a transparent appearance for navigationController?.navigationBar.standardAppearance.

UIMenuController not showing when UICollectionViewCell's subView has userInteraction Enabled

Basically I have an imageView inside cell whose isUserInteractionEnabled is set to true as it has a UITapGestureRecognizer. Now the problem is when I long press the cell outside the imageView area it shows the menu but when I long the imageView itself the menu isn't shown. I didn't understand the behaviour.
I also noticed that even if I remove UITapGestureRecognizer, it still doesn't work. So it has something to do with isUserInteractionEnabled property.
Just disable the user interaction on the image view, because it blocks the interaction on the cell.
imageView.isUserInteractionEnabled = false

How to prevent a UILabel from blocking a touch to a parent UIButton in Swift?

I have a UIButton that has four child UILabels that contain information about the button's functionality. When I click the center of the button the action does not fire because it is being blocked by the UILabels but when I click the outside of the button the action does fire. Is there a way to prevent the UILabels from blocking the action firing?
You'll need to set isUserInteractionEnabled = false on any view that is above the button, or a subview of it.
By default UILabel have it set to false, but as you mentioned in the comments, UIStackView does not. So calling isUserInteractionEnabled = false on it will do the trick ┌( ಠ‿ಠ)┘

Gracefully cancel UIScrollView touch (with animation)

There are myriad answers on cancelling a UIScrollView's touches (example SO question). However, the generally accepted answer (see prior example) is to do this by directly cancelling the scrollView's gesture recogniser, as below:
// Reset a scrollView's current 'touch'
scrollView.panGestureRecognizer.enabled = false
scrollView.panGestureRecognizer.enabled = true
The issue I'm currently having with this solution is that it cancels the ability for the scrollView to animate smoothly, and results in jumpy behaviour once you try to manipulate/animate the scrollView's contentOffset property.
In short, what I am trying to do is: once a paged scrollView reaches a certain content offset above its current page, cancel the current touch on the scrollView, animate back to the current page, and only then allow touches once more. You can liken this to having a scrollView containing a deck of cards that are only able to be scrolled through in one direction — if you attempt to go back (up) a card in the scrollView, you are stopped at a certain offset and the scrollView force-animates back down to the card you were on.
[Note — I understand there are other, more efficient ways to do this with gesture recognisers and custom views, but my need for a scrollView is more nuanced]
My code below (via my scrollView's delegate), cancels the current touch, but does not allow animation to happen. It simply 'snaps' back to place. Interestingly, without the pan gesture reset, the animation does happen — but of course since the pan gesture has not been reset the touch is allowed to continue dragging (even with userInteractionEnabled set to false).
// Delegate methods
func scrollViewDidScroll(scrollView: UIScrollView) {
if (scrollView.contentOffset.y <= (scrollView.frame.height PAGE_NUMBER - OFFSET_MARKER) {
// Where PAGE_NUMBER is the current page, and OFFSET_MARKER is the amount of pixels to trigger at, i.e. 80px
// Temporarily stop further user interaction
scrollView.userInteractionEnabled = false
// Reset the pan gesture recogniser -- THIS CAUSES 'SKIPPING' OF ANIMATION
scrollView.panGestureRecognizer.enabled = false
scrollView.panGestureRecognizer.enabled = true
// I have tried both 'animated: true / false'
UIView.animateWithDuration(0.4, animations: {
scrollView.setContentOffset(CGPointMake(0, self.frame.height), animated: true)
}, completion: { (complete) in
if complete{
// Re-enable user interaction (more touches)
scrollView.userInteractionEnabled = true
}
})
}
}
Any thoughts? Hopefully I'm missing something...
It turns out that the snapiness attributed to momentarily disabling the panGestureRecognizer stems from the scrollView being paged. Therefore, setting the scrollView.pagingEnabled property to false (temporarily in the delegate) solves it for me.
Not sure why it acts in this way, but I will do more digging and potentially file a bug report.

User Interaction enabled No Only to the parent

I have one scroll view (UserInteractionEnabled = No) with one image view as its subview.
I am assigning tap gesture to imageview but it is not working even if imageview is UserInteractionEnabled because Its parent (ScrollView) is not.
How can I resolve this conflict.
There is no reason to disable user interaction on a scroll view. If you want to block the scrolling, disable it using the scrollEnabled property.
Don't set scroll view (UserInteractionEnabled = No) because it will set to all its subViews.
hope it will work.

Resources