My collection view is working great. It shows a grid of photos and lists hundreds of them. You can swipe vertically to scroll through them all. Life is good. However, I now have a new requirement. I need to be able to detect when the user is swiping left or right. I need to be able to intercept this gesture so I can attach behavior to left and right swipes while keeping intact my collection view's vertical scroll capabilities. Any ideas?
In swift?
If it helps for reference heres a link to my Github project.
https://github.com/StarShowsStudios/GodCards
If you open the project in Xcode you can see the detail view controller. It gets its information from a plist file called cards according to the selected collection cell controller
You can add left and right swipe gesture recognizer to detect left and right swipe.
override func awakeFromNib() {
super.awakeFromNib()
// Add Left Swipe Gesture
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(SomeClass.respondToSwipeGesture(_:)))
swipeLeft.direction = UISwipeGestureRecognizerDirection.Left
self.addGestureRecognizer(swipeLeft)
// Add Right Swipe Gesture
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(SomeClass.respondToSwipeGesture(_:)))
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
self.addGestureRecognizer(swipeRight)
}
// This function detects Swipe direction and perform action
func respondToSwipeGesture(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Right:
print("Swiped right")
rightSwipeAction()
case UISwipeGestureRecognizerDirection.Left:
print("Swiped left")
leftSwipeAction()
default:
break
}
}
}
Related
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")
}
}
Edit: it seems the swipe gesture can only takes one direction a time now. If someone knows another way to handle multiple directions at once, I’d still appreciate information!
Eidt: I find a way to deal with multiple directions concisely in this [answer] (https://stackoverflow.com/a/46104997/9645644) It uses an array literal with forEach loop. It’s much more convenient than adding gestures and dragging actions separately from storyboard.
I’m trying to get swift swipe gestures to work, everything’s fine until I tried to detect the direction of the swipe. Below is my code. I don’t understand why this isn’t working and would appreciate help!
In a view controller’s viewDidLoad I set up and added the swipe gesture recognizer, with direction[.left, .right]. After that I implemented the handler method which needs to detect the direction of the swipe. There’s no other stuff in this view controller.
After it failed to work(no response when swipe), I added a few prints, and got the output in the title.
override func viewDidLoad() {
super.viewDidLoad()
let swipeGestureRecognizer = UISwipeGestureRecognizer(target:self, action:#selector(swipeHandler(recognizer: )))
swipeGestureRecognizer.direction = [.left, .right]
view.addGestureRecognizer(swipeGestureRecognizer)
}
#objc func swipeHandler (recognizer: UISwipeGestureRecognizer){
switch recognizer.state{
case .ended:
let direction = recognizer.direction
print(direction)
if direction == .left {print(”left”)}
else if direction == .right {print(“right”)}
else {print(print(“none”)}
defaul: break
}
No matter left or right I swipe, it always prints “none”. And the direction print always give a “UISwipeGestureRecognizerDirection(rawValue: 3)”
The direction property tells the gesture when to trigger. for example if direction == .right then the swipe will trigger only on a swipe to the right. (It does not tell you the direction detected)
You need to detect one direction at a time. I would also suggest to add a method to control each swipe direction. For example.
func setUpGestures() {
// Gesture that define a left swipe.
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(Scene.swipeLeft))
swipeLeft.direction = .left
view?.addGestureRecognizer(swipeLeft)
// Do the same for the rest of the directions.
}
#objc func swipeLeft() {
// Do something when the user swipe left.
}
Hope it helps!
I'm trying to create a keyboard the allows single tap, double tap, and triple tap. So I want to add a UITapGestureRecognizer() to each button in my keyboard. I know how to do this manually from the xib file (add each letter it's own gesture, which would take ages) but not quite sure how to do it in the Controller.
I wrote this for double tap in the viewDidLoad() method:
let doubleTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "doubleTapCharacter:")
doubleTap.numberOfTapsRequired = 2
for button in self.view.subviews{
button.addGestureRecognizer(doubleTap)
}
and created a doubleTapCharacter() method but it's still not working. I also want to be able to send information to the doubleTapCharacter method.
Any help would be much appreciated. Also, I'm very new to swift so if the instructions are complicated, I'd highly appreciate it if you can break it down a little.
create and add the gesture recognizers:
for button in view.subviews {
// create the gesture recognizer
let doubleTapRecognizer = UITapGestureRecognizer(target: self, action: "doubleTapCharacter:")
doubleTapRecognizer.numberOfTapsRequired = 2
// add gesture recognizer to button
button.addGestureRecognizer(doubleTapRecognizer)
}
then implement the target method:
func doubleTapCharacter(doubleTapRecognizer: UITapGestureRecognizer) {
let tappedButton = doubleTapRecognizer.view as! UIButton
print(tappedButton.titleForState(UIControlState.Normal))
}
I'm trying to add the swipe gesture recognizer to the collection view by using swift. Everytime the user swipe to right or left, I want my collection view reload. However, when I swipe to right or left in collection view on the simulator, it gives me an error and AppDelegate.swift class is automatically opened. The error says " libc++abi.dylib: terminating with uncaught exception of type NSException "
I write this part to the viewDidLoad() in the collectionViewController class
collectionView.userInteractionEnabled = true
collectionView.delegate = self
var left = UISwipeGestureRecognizer(target: collectionView, action: "swipping:")
left.direction = UISwipeGestureRecognizerDirection.Left
collectionView.addGestureRecognizer(left)
var right = UISwipeGestureRecognizer(target: collectionView, action: "swipping:")
right.direction = UISwipeGestureRecognizerDirection.Right
collectionView.addGestureRecognizer(right)
This is the swipping function:
func swipping (gesture : UIGestureRecognizer){
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Left:
collectionView.reloadData()
pageControl.currentPage++
case UISwipeGestureRecognizerDirection.Right:
collectionView.reloadData()
pageControl.currentPage--
default:
break
}
}
}
Added UIGestureRecognizerDelegate to the CollectionViewController class and AppDelegate class. What should I do?
Thanks.
When you declare gesture recogniser you specify collectionView as a target:
var left = UISwipeGestureRecognizer(target: collectionView, action: "swipping:")
But I believe the swiping: method is placed in the same file where the declaration is taking place.
You have to change target to self:
var left = UISwipeGestureRecognizer(target: self, action: "swipping:")
var right = UISwipeGestureRecognizer(target: self, action: "swipping:")
//Extended
This is not working because UICollectionView is a subclass of UIScrollView and when you swipe UIScrollView handle the gesture (this is because you can create collection in horizontal direction so collection view needs to know that you are scrolling left/right).
You should consider override UIScrollViewDelegate method:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
to find out the swipe and you should handle it instead of adding gesture recogniser.
Try something like that:
//Declare private property
#property (nonatomic, assign) CGFloat prevOffset
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (self.prevOffset > scrollView.contentOffset.x)
// You are swiping right
else if (self.prevOffset < scrollView.contentOffset.x)
// You are swiping left
self.prevOffset = scrollView.contentOffset.x;
}
In my iPhone app, I require to recognize the swipe gesture made by the user on the view.
I want the swipe gestures to be recognized and perform a function on swipe.
I need that the view should horizontally slide and show another view as a user makes a swipe gesture.
What needs to be done?
How do I recognize it?
If You know how it works, but still need a quick example, here it is! (it will become handy at least for me, when I will need copy-paste example, without trying remembering it)
UISwipeGestureRecognizer *mSwipeUpRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(doSomething)];
[mSwipeUpRecognizer setDirection:(UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight)];
[[self view] addGestureRecognizer:mSwipeUpRecognizer];
and in .h file add:
<UIGestureRecognizerDelegate>
Use the UISwipeGestureRecognizer. Not much else to say really, gesture recognizers are easy. There are WWDC10 videos on the subject even. Sessions 120 and 121. :)
The following link below redirects you to a video tutorial which explains you how to detect swipes on the iPhone in Objective-C:
UISwipeGestureRecognizer Tutorial (Detecting swipes on the iPhone)
Code sample below, to achieve that in Swift:
You need to have one UISwipeGestureRecognizer for each direction. It's a little weird because the UISwipeGestureRecognizer.direction property is an options-style bit mask, but each recognizer can only handle one direction. You can send them all to the same handler if you want, and sort it out there, or send them to different handlers. Here's one implementation:
override func viewDidLoad() {
super.viewDidLoad()
var swipeRight = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
self.view.addGestureRecognizer(swipeRight)
var swipeDown = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeDown.direction = UISwipeGestureRecognizerDirection.Down
self.view.addGestureRecognizer(swipeDown)
}
func respondToSwipeGesture(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Right:
println("Swiped right")
case UISwipeGestureRecognizerDirection.Down:
println("Swiped down")
default:
break
}
}
}
Swift 5 version:
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGestureRight))
swipeRight.direction = UISwipeGestureRecognizer.Direction.right
self.view.addGestureRecognizer(swipeRight)