Xcode & Swift - Detecting user touch of UIView inside of UIScrollView
By setting userInteractionEnabled
to NO
for your scroll view, the view controller will start receiving touch events since UIViewController
is a subclass of UIResponder
. You can override one or more of these methods in your view controller to respond to these touches:
- touchesBegan: withEvent:
- touchesMoved: withEvent:
- touchesEnded: withEvent:
- touchesCancelled: withEvent:
I created some example code to demonstrate how you could do this:
class ViewController: UIViewController {
@IBOutlet weak var scrollView: UIScrollView!
// This array keeps track of all obstacle views
var obstacleViews : [UIView] = []
override func viewDidLoad() {
super.viewDidLoad()
// Create an obstacle view and add it to the scroll view for testing purposes
let obstacleView = UIView(frame: CGRectMake(100,100,100,100))
obstacleView.backgroundColor = UIColor.redColor()
scrollView.addSubview(obstacleView)
// Add the obstacle view to the array
obstacleViews += obstacleView
}
override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) {
testTouches(touches)
}
override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) {
testTouches(touches)
}
func testTouches(touches: NSSet!) {
// Get the first touch and its location in this view controller's view coordinate system
let touch = touches.allObjects[0] as UITouch
let touchLocation = touch.locationInView(self.view)
for obstacleView in obstacleViews {
// Convert the location of the obstacle view to this view controller's view coordinate system
let obstacleViewFrame = self.view.convertRect(obstacleView.frame, fromView: obstacleView.superview)
// Check if the touch is inside the obstacle view
if CGRectContainsPoint(obstacleViewFrame, touchLocation) {
println("Game over!")
}
}
}
}
Detect touch on UIButton below UIScrollview
I am not a Swift coder, i could link you all the methods , but I guess you can handle it yourself, unless you can't let me know I will update the answer. However, the solution for you:
First you need to add a UITapGestureRecognizer with a single tap to your UIScrollView.
Detect the tap CGPoint (user touchpoint) inside your tapGesture method:
(Objective-c)
CGPoint touchPoint=[gesture locationInView:scrollView];
Then do a check if the touchPoint is inside the view below it with CGRectContainsPoint
bool CGRectContainsPoint(CGRect rect, CGPoint point);
If so, just fire the action, otherwise ignore it. :)
Touch events on subclass of UIView as a subview of UIScrollView
There are several approaches you could try:
Try setting the below properties on the
UIScrollView
:scrollView.delaysContentTouches = NO;
scrollView.canCancelContentTouches = NO;
See similar SO questions/answers here, here.
Implement
hitTest:withEvent:
. See here, here.Use a
UIGestureRecognizer
. See here, here.
I would personally recommend using a UIGestureRecognizer
, but it depends on your specific situation (any of these options may work fine for you).
Detect Touch Event On UIScrollView's Content
Your UIImageView
s probably have user interaction disabled (which is what they default to). Call the following line on each image view, and your taps should be recognized:
yourImageView.userInteractionEnabled = YES;
Make sure to do this before adding the gesture recognizer.
I had this exact issue a few weeks ago and this is what fixed it for me.
UiScrollview scrollviewDidScroll detect user touch
The UIScrollView
has a panGestureRecogniser
property, which tracks the pan gestures in the scroll view. You can track the state
of the pan gesture in the scrollViewDidScroll
to know exactly what state the panning is in.
Swift 4.0
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.isEqual(yourScrollView) {
switch scrollView.panGestureRecognizer.state {
case .began:
// User began dragging
print("began")
case .changed:
// User is currently dragging the scroll view
print("changed")
case .possible:
// The scroll view scrolling but the user is no longer touching the scrollview (table is decelerating)
print("possible")
default:
break
}
}
}
Objective-C
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if ([scrollView isEqual:yourScrollView]) {
switch (scrollView.panGestureRecognizer.state) {
case UIGestureRecognizerStateBegan:
// User began dragging
break;
case UIGestureRecognizerStateChanged:
// User is currently dragging the scroll view
break;
case UIGestureRecognizerStatePossible:
// The scroll view scrolling but the user is no longer touching the scrollview (table is decelerating)
break;
default:
break;
}
}
}
UIView inside UIScrollView not getting touch events
You may have solved this now but I had a similar problem and solved it so hopefully my experience can help anyone else with a similar issue.
In my case I had exactly the same setup my CustomUIView was capturing the touch events. In order to have UIView receive any touch events I needed to make a call to
[super touchesEnded:touches withEvent:event];
from the CustomUIView. Hope this helps!
How to capture touch events from a UIScrollView when user is scrolling the screen vertically on iOS with Swift?
So UIScrollView has its own set of gestures that have cancelsTouchesInView
set to true by default. Try setting this property to false
for each gesture in the scrollview like so:
for gesture in scrollView.gestureRecognizers ?? [] {
gesture.cancelsTouchesInView = false
}
EDIT:
Solution to this problem is creating a separate custom UIScrollView
and capture touches inside it. It is described in details in this thread: https://stackoverflow.com/a/70594220/10953499 (also linked in the comment).
Related Topics
Tableview Rounded Corners and Shadow
How to Make Cmake Use Specific Compiler and Flags When Final Compilation Stage Instead of Detection
How to Know All My Tasks in Grand Central Dispatch Finished
How to Get Enum from Raw Value in Swift
Safeareainsets in Uiview Is 0 on an iPhone X
Nsdictionaryofvariablebindings Swift Equivalent
Filenames Are Used to Distinguish Private Declarations of the Same Name' Error
How to Convert String to Date to String in Swift iOS
Where Does the Indexpath of Dequeuereusablecellwithidentifier:Forindexpath: Get Used
How to Set Multi Line Large Title in Navigation Bar? ( New Feature of iOS 11)
Scale Text Label by Screen Size
Uicollectionview Cell Spacing Based on Device Screen Size
Adding Private Key into iOS Keychain
Simplified Screen Capture: Record Video of Only What Appears Within the Layers of a Uiview
App Transport Security Does Not Work Any More with iOS 11 Xcode 9