Reputation: 2274
The problem is quite simple: I have a ViewController
on which I have a GestureRecognizer
:
panGR = UIPanGestureRecognizer(target: self,
action: #selector(handlePan(gestureRecognizer:)))
view.addGestureRecognizer(panGR)
In this ViewController
I also have a class WhishlistTableViewController: UITableViewController
on which I have the "swipe-to-delete"-function:
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: "Löschen") {[weak self] _, _, completionHandler in
self!.deleteWishDelegate?.deleteWish(indexPath)
completionHandler(true)
}
deleteAction.backgroundColor = .red
deleteAction.image = UIImage(systemName: "trash")
let configuration = UISwipeActionsConfiguration(actions: [deleteAction])
configuration.performsFirstActionWithFullSwipe = false
return configuration
}
Here is a Video of my panGR
in action: Screenvideo
This is my handlePan
function:
// handle swqipe down gesture
@objc private func handlePan(gestureRecognizer:UIPanGestureRecognizer) {
// calculate the progress based on how far the user moved
let translation = panGR.translation(in: nil)
let progress = translation.y / 2 / view.bounds.height
switch panGR.state {
case .began:
// begin the transition as normal
self.dismissView()
break
case .changed:
Hero.shared.update(progress)
default:
// finish or cancel the transition based on the progress and user's touch velocity
if progress + panGR.velocity(in: nil).y / view.bounds.height > 0.3 {
self.dismissView()
Hero.shared.finish()
} else {
Hero.shared.cancel()
}
}
}
The problem is that these two collide. The "swipe-to-delete" only works if I disable the other GestureRecognizer
. Why is that and how can I solve this ?
Upvotes: 0
Views: 1159
Reputation: 2274
With the help of Mitesh Mistri I got it working. One more thing that was missing was a function to disable the panGR
inside the tableView
because otherwise the user wouldnt be able to scroll. These are the two function that made it work:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if self.theTableView.view.bounds.contains(touch.location(in: self.theTableView.view)) {
return false
}
return true
}
Upvotes: 0
Reputation: 24
Normally this is simple,
Firstly , you don't need to add a gesture recognizer to the view,
we already have the function "touchesBegan" which Tells this object that one or more new touches occurred in a view or window.
so in your code you just need to use it instead of the gesture recognizer and it will works.
class ViewController: UIViewController,UITableViewDataSource {
let tableView:UITableView = {
let table = UITableView()
table.backgroundColor = .blue
table.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
return table
}()
override func viewDidLoad() {
super.viewDidLoad()
// tableView.delegate = self
tableView.dataSource = self
view.addSubview(tableView)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableView.frame = CGRect(x: 0, y: view.frame.height/2, width: view.frame.width, height:view.frame.height/2 )
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.backgroundColor = .blue
return cell
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return
}// we store the touch
let location = touch.location(in: view)//we retrieve the location of the touch
if view.bounds.contains(location){//we check if our touch is inside our view
// if our touch is inside the view ,do the action you wanted to do with your gesture recognizer
print("inside the view, outside tableView(Controller)")
}else{
// else here means here that this is not inside the view, so it is inside the tableView(Controller)
// if this is not inside the view, you can select tableView,rows,swipe-to-delete etc, basically do whatever action you want with it
}
}
}
Upvotes: -1
Reputation: 1162
When you do pan gesture on top of the view the gesture pan recognizer will be invoked. If the tableview is part of the view the gesture handlePan will be called when you try to do swipe-to-delete function.
If you want 2 separate behavior then separate the part of the view in which you want gesture handlePan to execute and tableview where you want swipe-to-delete function to execute.
Something like below :
panGR = UIPanGestureRecognizer(target: self,
action: #selector(handlePan(gestureRecognizer:)))
gestureView.addGestureRecognizer(panGR)
view.addSubView(gestureView)
EDIT: You can also get the location/co-ordinates of the location pressed and you can calculate which areas to ignore.
currentLocation = gesture.location(in: self.view)
Upvotes: -1
Reputation: 459
You should try this.
class YourViewController: UIViewController, UIGestureRecognizerDelegate
in viewDidLoad
yourGesture.delegate = self
and finally
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
// If you wish to do conditionally.
/*if (gestureRecognizer is UIPanGestureRecognizer || gestureRecognizer is UIRotationGestureRecognizer) {
return true
} else {
return false
}*/
}
Upvotes: 3