I am implementing a gesture recognizer for swiping in Swift. I wan to be able to simulate the flinging of the card (programmatically swipe the view).
I assumed there would be a built in function for this but all I have found is one for tap gesture not swipe gesture.
This is how I am implementing the swipe gesturing:
let gesture = UIPanGestureRecognizer(target: self, action: Selector("wasDragged:"))
cardView.addGestureRecognizer(gesture)
cardView.userInteractionEnabled = true
}
func wasDragged (gesture: UIPanGestureRecognizer) {
let translation = gesture.translationInView(self.view)
let cardView = gesture.view!
// Move the object depending on the drag position
cardView.center = CGPoint(x: self.view.bounds.width / 2 + translation.x,
y: self.view.bounds.height / 2 + translation.y)
You can't simulate a gesture recognizer in its full implications (I mean, you can't actually make iOS think it's a real user action).
You can, however, fool your own code making it act as if it were a real swipe. For that, you need to create a gesture recognizer first:
var gestureRecognizerSwipeRight = UISwipeGestureRecognizer(target: self, action: "activatedGestureRecognizer:")
gestureRecognizerSwipeRight.direction = UISwipeGestureRecognizerDirection.Right
yourView.addGestureRecognizer(gestureRecognizerSwipeRight)
And then pass it directly to your action:
// Some other place in your code
self.activatedGestureRecognizer(gesture: gestureRecognizerSwipeRight)
Your activatedGestureRecognizer(gesture:) method should be something like:
func activatedGestureRecognizer(gesture: UIGestureRecognizer) {
if let gestureRecognizer = gesture as? UIGestureRecognizer {
// Here you can compare using if gestureRecognizer == gestureRecognizerSwipeRight
// ...or you could compare the direction of the gesture recognizer.
// It all depends on your implementation really.
if gestureRecognizer == gestureRecognizerSwipeRight {
// Swipe right detected
}
}
}
In fairness, I don't see any real gain in doing it this way. It should be a lot better to simply do the action associated with the swipe instead of actually simulating the gesture recognizer.
If you need, for instance, to animate your card while swipping, why don't you simply disable the user interaction on your card view and animate it programmatically?
Here is code you can use to programatically swipe the cell. When performed, the cell will animate to the swiped position.
#IBAction
func swipeFirstCell() {
if let cell = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) {
tableView.perform(Selector("_endSwipeToDeleteRowDidDelete:"), with: nil) // cancel any existing swipes
tableView.perform(Selector("_swipeToDeleteCell:"), with: cell)
}
}
Note you need to also return true for the cell from canEditRowAtIndexPath.
This might get flagged by Apple's private API detection but you can at least use it for development and perhaps obfuscate the string if you really to.
For SWIFT 3.0
let swipeRightOrange:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(slideToRightWithGestureRecognizer))
swipeRightOrange.direction = .Right;
let swipeLeftOrange:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(slideToLeftWithGestureRecognizer))
swipeLeftOrange.direction = .Left;
#IBAction func slideToLeftWithGestureRecognizer(gestureRecognizer:UISwipeGestureRecognizer)
{
viewOrange.backgroundColor = UIColor.blue
}
#IBAction func slideToRightWithGestureRecognizer(gestureRecognizer:UISwipeGestureRecognizer)
{
viewOrange.backgroundColor = UIColor.lightGray
}
You can create the UIPanGestureRecognizer by yourself and pass it to the wasDragged method. You should check with different values of the translation though:
let gesture = UIPanGestureRecognizer()
gesture.setTranslation(CGPointMake(0, 100), inView: self.view)
wasDragged(gesture)
SWIFT 4.2
let gesture = UIPanGestureRecognizer()
gesture.setTranslation(CGPoint(x: 0, y: 100), in: self.view)
wasDragged(gesture)
Although I asume you need something else. Why do you need to simulate this gesture in the first place?
You need to implement UISwipeGestureRecognizer
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:
print("Swiped right")
case UISwipeGestureRecognizerDirection.Down:
print("Swiped down")
case UISwipeGestureRecognizerDirection.Left:
print("Swiped left")
case UISwipeGestureRecognizerDirection.Up:
print("Swiped up")
default:
break
}
}
}
Related
I have developed a UIView from For loop and basically it is create 3 Views from loop. and I have to add touch gesture on every View to call a method but I am unable to get current selected UIView.tag when I tap on it. it is only showing the .tag of the last view. here is my code.
for i in 0 ... 2 {
let productView = UIView()
productView.tag = i
productView.isUserInteractionEnabled = true
let producttap = UITapGestureRecognizer(target: self, action: #selector(self.ProductTapped))
productView.addGestureRecognizer(producttap)
productView.frame = CGRect(x: xOffset, y: CGFloat(buttonPadding), width: 200, height: scView1.frame.size.height)
xOffset = xOffset + CGFloat(buttonPadding) + productView.frame.size.width
scView1.addSubview(productView)
productIndex = productView.tag
}
and here is the method that I am calling from every UIView touch.
#objc func ProductTapped() {
print("",productIndex)
}
Your code should be using delegate/callback closure, but if you want to keep using tag, try change it to:
#objc func ProductTapped(_ sender: UITapGestureRecognizer) {
if let view = sender.view {
print(view.tag)
}
}
and the gesture attach to let producttap = UITapGestureRecognizer(target: self, action: #selector(self.ProductTapped(_:)))
productIndex does nothing here since it got overwritten on the loop
productIndex currently has no relationship to the tap gestures that you attach your views. You do set productIndex in the the loop but that's irrelevant to your gesture.
Perhaps you want
let producttap = UITapGestureRecognizer(target: self, action: #selector(productTapped(_:))
and
#objc func productTapped(_ gesture: UITapGestureRecognizer) {
print("tag is",gesture.view.tag)
}
Is it possible to increase edge size interactivePopGestureRecognizer of UINavigationController reacts user touches?
I.e. is it possible to make swipe right from middle of screen to move and pop current top Viewcontroller same way as from the left screen edge?
override func viewDidLoad() {
super.viewDidLoad()
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture))
swipeRight.direction = .right
self.view.addGestureRecognizer(swipeRight)
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture))
swipeLeft.direction = .left
self.view.addGestureRecognizer(swipeLeft)
}
// you can track all direction swipe like below, and to do that first you have to add gesture in the view you want to track.
#objc func respondToSwipeGesture(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case .right:
// push pop here
print("Swiped right")
case .down:
print("Swiped down")
case .left:
// push pop here
print("Swiped left")
case .up:
print("Swiped up")
default:
break
}
}
}
Finally, found a solution to increase the edge touch size using this library: SwipeTransition
I have a view that has panGesture functionality, but I need to send a pan-gesture from one point to another programatically. Is there a way to do this in swift using an animation with a specific time interval? Here is my attempt at calling the pan gesture programmatically:
var upPanPoint = CGPoint(x: contentView.center.x, y: contentView.center.y + 500)
var upPan = panGestureRecognizer.setTranslation(upPanPoint, inView: self)
onSwipe(upPan)
here is the code that recognizes the pan gesture:
func onSwipe(panGestureRecognizer : UIPanGestureRecognizer!) {
let view = panGestureRecognizer.view!
print(view)
switch (panGestureRecognizer.state) {
case UIGestureRecognizerState.Began:
if (panGestureRecognizer.locationInView(view).y < view.center.y) {
self.viewState.rotationDirection = .RotationAwayFromCenter
} else {
self.viewState.rotationDirection = .RotationTowardsCenter
}
case UIGestureRecognizerState.Ended:
self.finalizePosition()
default:
let translation : CGPoint = panGestureRecognizer.translationInView(view)
view.center = self.viewState.originalCenter + translation
self.rotateForTranslation(translation, withRotationDirection: self.viewState.rotationDirection)
self.executeOnPanForTranslation(translation)
}
}
// The Pan Gesture
func createPanGestureRecognizer(targetView: UIImageView) {
var panGesture = UIPanGestureRecognizer(target: self, action:("handlePanGesture:"))
targetView.addGestureRecognizer(panGesture)
}
func handlePanGesture(panGesture: UIPanGestureRecognizer) {
// get translation
var translation = panGesture.translationInView(view)
panGesture.setTranslation(CGPointZero, inView: view)
println(translation)
// create a new Label and give it the parameters of the old one
var label = panGesture.view as UIImageView
label.center = CGPoint(x: label.center.x+translation.x, y: label.center.y+translation.y)
label.multipleTouchEnabled = true
label.userInteractionEnabled = true
if panGesture.state == UIGestureRecognizer.State.began {
// add something you want to happen when the Label Panning has started
}
if panGesture.state == UIGestureRecognizer.State.ended {
// add something you want to happen when the Label Panning has ended
}
if panGesture.state == UIGestureRecognizer.State.changed {
// add something you want to happen when the Label Panning has been change ( during the moving/panning )
} else {
// or something when its not moving
}
}
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture))
self.imageView.addGestureRecognizer(panGesture)
#objc func panGesture(sender: UIPanGestureRecognizer){
let point = sender.location(in: view)
let panGesture = sender.view
panGesture?.center = point
print(point)
}
With Swift version 4.2 you can set pan gesture programmatically using below code:
let panGesture = UIPanGestureRecognizer(target: self, action:(#selector(self.handleGesture(_:))))
self.view.addGestureRecognizer(panGesture)
#objc func handleGesture(_ sender: UIPanGestureRecognizer) {
switch sender.state {
case .began:
case .changed:
case .cancelled:
case .ended:
default:
break
}
}
How can I implement a swipe gesture to change view to and fro?
The best example I've seen so far is the Soundcloud application but I couldn't figure out how to make it work.
Compatible with Swift 5
override func viewDidLoad()
{
super.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)
}
#objc func handleSwipes(_ sender: UISwipeGestureRecognizer)
{
if sender.direction == .left
{
print("Swipe left")
// show the view from the right side
}
if sender.direction == .right
{
print("Swipe right")
// show the view from the left side
}
}
Use this code...
override func viewDidLoad() {
super.viewDidLoad()
var swipeRight = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
self.view.addGestureRecognizer(swipeRight)
}
func respondToSwipeGesture(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Right:
println("Swiped right")
//change view controllers
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let resultViewController = storyBoard.instantiateViewControllerWithIdentifier("StoryboardID") as ViewControllerName
self.presentViewController(resultViewController, animated:true, completion:nil)
default:
break
}
}
}
You can a UISwipeGestureRecognizer to your UIView and add to this gesture a target and an action to perform when the gesture occurs
var swipeGesture = UISwipeGestureRecognizer(target: self, action: "doSomething")
myView.addGestureRecognizer(swipeGesture)
func doSomething() {
// change your view's frame here if you want
}
This tutorial might be helpful to you: http://www.avocarrot.com/blog/implement-gesture-recognizers-swift/
Basically, you'll need to add a gesture recognizer to your view that listens for swipe gestures. Then when it detects a swipe, push to the next view.
How can I make a transition from left to right using performseguewithidentifier? What I want to do is when user swipe to right, the page/view controller's transition will switch from right to left, normally it will swipe from left to right. Is this possible?
My code:
override func viewDidLoad() {
var swipeRight = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
self.view.addGestureRecognizer(swipeRight)
}
func respondToSwipeGesture(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Right:
performSegueWithIdentifier("LeftSegue", sender: self)
println("Swiped right")
default:
break
}
}
}
You have to write your own custom interactive transition.
Here and here you can find example tutorial. It's quite easy but have a little bit of boiler plate code.