I'm working on a small SpriteKit game for tvOS. I need to receive input when the user clicks the play/pause button on the remote. Looking at the docs, it appears that I should just have to add a UITapGestureRecognizer to my scene's view. I implemented the following code:
override func didMove(to view: SKView) {
let tapPlayPause = UITapGestureRecognizer(target: self, action: #selector(tapTesting))
tapPlayPause.allowedPressTypes = [NSNumber(value: UIPress.PressType.playPause.rawValue)]
view.addGestureRecognizer(tapPlayPause)
let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(swipeUp))
swipeUp.direction = .up
view.addGestureRecognizer(swipeUp)
}
#objc func tapTesting(_ sender: UITapGestureRecognizer) {
print("TAP")
}
However, when I run the app on my Apple TV 4K (running tvOS 15), there is no output and from what I can tell no tap code is getting triggered.
I have tried the code with self.isUserInteractionEnabled = true as well but I still do not receive tap inputs.
The swipe gesture I implemented above works perfectly thought, and the tap gesture works on my iOS devices. Does anyone have any idea as to why this is the case?
Thanks!
For tvOS gestures, you also need to set allowedTouchTypes to .indirect
tapPlayPause.allowedTouchTypes = [NSNumber(touchType: .indirect)]
I have a UIScrollView inside which I have a UIView which has 5 UITextViews. All this works fine and I'm able to scroll up and down. I have a UISwipeGestureRecognizer connected to the UIScrollView programatically.
When I receive a swipe notification I update the contents of the 5 text views. However it takes upto 30 seconds for the updated text to actually appear. If I update the contents of the 5 text views inside a button press handler, they update immediately.
I have tried calling setNeedsDisplay() on scrollView as well as contentView. This did not help. I also tried scrolling the scrollView programatically, and that did not help either. I have verified that the swipe gesture handler is running in the same thread as the UI.
This the code inside my viewDidLoad()
let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipes(_:)))
let rightSwipe = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipes(_:)))
leftSwipe.direction = .left
rightSwipe.direction = .right
view.addGestureRecognizer(leftSwipe)
view.addGestureRecognizer(rightSwipe)
And these are my callbacks
#objc func handleSwipes(_ sender: UISwipeGestureRecognizer)
{
if sender.direction == .left
{
print("swipe left")
}
else if sender.direction == .right
{
print("swipe right")
}
}
if I add tapgesture on background view then I have to long press for select cell and if I set numberoftaprequired is 2 the it will be work normally but I have to give one functionality on single tap
add cancelsTouchesInView to your tap gesture
let tap = UITapGestureRecognizer(target: self, action: #selector(yourfunction))
tap.cancelsTouchesInView = false
try this
I have create an date component and have problems with the GestureRecognizer.
First line is a StackView with labels. If I attach a TapGestureRecognizer it is fired on touch. The following Lines are subviews in a Stackview consisting of a label and an image view. I can add the Recognizer to the subview, to the label or the image view. It never gets fired and I made sure that userInteraction is enabled.
What could be the problem?
Here an example how I add the recognizer:
func addTap(){
dayLabel.isUserInteractionEnabled = true
imageView.isUserInteractionEnabled = true
isUserInteractionEnabled = true
tap1 = UITapGestureRecognizer(target: self, action: #selector(handleTap(recognizer:)))
tap2 = UITapGestureRecognizer(target: self, action: #selector(handleTap(recognizer:)))
tap3 = UITapGestureRecognizer(target: self, action: #selector(handleTap(recognizer:)))
dayLabel.addGestureRecognizer(tap1!)
imageView.addGestureRecognizer(tap2!)
addGestureRecognizer(tap3!)
}
#objc func handleTap(recognizer: UITapGestureRecognizer){
logger.debug("tap")
changeSelection()
}
You can find a little demo project boiled down to the problem here: https://github.com/ogezue/datedemo
Problem I can see is your view must be cover with Image and label
and you are adding same UITapGestureRecognizer to all so that is added on last object say view (which is covered with image and label) so it may not able to get tap event
You need three different objects of UITapGestureRecognizer you can't add same tap gesture on different views
Hope it may solve your problem
For every view (Label/Imageview) you should create a tap object not the same one added to both . . .
I have a UIScrollView to which I added a single tap gesture recognizer to show/hide some UI overlay using:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[scrollView addGestureRecognizer:singleTap];
and:
- (void)handleTap:(UITapGestureRecognizer *)sender {
// report click to UI changer
}
I added an easy table view to the bottom of the UIScrollView. Everything works right (scrolling both horizontally and vertically) but the problem is that taps are recognized only by the gesture recognizer (above), but not by the easy table view.
If I remove The line that registers the gesture listener, everything works fine, the table view notices taps on itself.
It's as if the gesture recognizer function "eats" the tap events on the table view and doesn't propagate them downward.
Any help is appreciated
This should solve your problem.
Detect touch event on UIScrollView AND on UIView's components [which is placed inside UIScrollView]
The idea is to tell the gesture recognizer to not swallow up the touch events. To do this you need to set singleTap's cancelsTouchesInView property to NO, which is YES by default.
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
singleTap.cancelsTouchesInView = NO;
[scrollView addGestureRecognizer:singleTap];
Swift 3.0
let singleTap = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
singleTap.cancelsTouchesInView = false
singleTap.numberOfTapsRequired = 1
scrollView.addGestureRecognizer(singleTap)
And the selector method be like.
#objc func handleTap(_ recognizer: UITapGestureRecognizer) {
// Perform operation
}
I think the reason is that User Interaction Enabled is set to false for UIImageView. You should set it to true to enable tapping in it
You can set which objects are to be included/excluded for touches.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gesture shouldReceiveTouch:(UITouch *)touch {
if (touch.view == [self view]) {
return YES;
}
return NO;
}
This worked for me in Swift 3 / Xcode 8
self.scrollView.touchesShouldCancel(in: ** the view you want the touches in **)
self.scrollView.canCancelContentTouches = false
Good luck!
Thanks #zambrey
Swift 2.2+ Version:
scrollView.delegate = self
let allowMultipleTouches = UITapGestureRecognizer(target: self, action: #selector(genderPressed))
allowMultipleTouches.numberOfTapsRequired = 1
allowMultipleTouches.cancelsTouchesInView = false
scrollView.addGestureRecognizer(allowMultipleTouches)
If your scroll view is in the Storyboard, don't forget to pin the Outlet in the view controller. In this example, scrollView is the Outlet of the UIScrollView.
TapGestures worked for me. The swipe on the other hand, I had to disable the scrolling and it worked.
swipeLeftGesture = UISwipeGestureRecognizer(target: self, action: #selector(swipeToNewImage(_:)))
swipeLeftGesture.direction = .left
scrollView.addGestureRecognizer(swipeLeftGesture)
swipeRightGesture = UISwipeGestureRecognizer(target: self, action: #selector(swipeToNewImage(_:)))
scrollView.addGestureRecognizer(swipeRightGesture)
scrollView.isScrollEnabled = false
You can capture any kind of gestures in the UIscrollView. Make sure you also handle some of the default properties as well like set cancelsTouchesInView property to false, it is true by default.
Also give some tag nos to your sub views to distinguish in selectors.
& also enable their User interaction to true.
let tap = UITapGestureRecognizer(target: self, action:
selector(didTapByUser(_:)))
My code.
I checked all proposed solutions and any work for me. I do not understand why. I do not understand the reason.
class MyClass: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))
scrollView.contentSize = CGSize(width: UIScreen.main.bounds.size.width, height: 800)
scrollView.isUserInteractionEnabled = true
scrollView.delegate = self
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(manageGesture))
tap.cancelsTouchesInView = false
tap.numberOfTapsRequired = 1
scrollView.addGestureRecognizer(tap)
scrollView.canCancelContentTouches = false
self.view.addSubview(scrollView)
}
#objc func manageGesture(){
// Some action
}
}