How to Configure Threshold/Distance When Swiping on Uitableviewcell

How to configure threshold/distance when swiping on UITableViewCell

There is no direct configuration method for it.

Solution

But you can build it yourself:

  • add a UIPanGestureRecognizer to the table
  • allow simultaneous recognitions of gestures
  • when a swipe ends check for direction and compute percentage out of the translation
  • determine the affected table row
  • delete it

Code

A swipe of the cells to the left by 20%, leading to the deletion of a row, would look like this in the code:

class ViewController: UITableViewController, UIGestureRecognizerDelegate {

override func viewDidLoad() {
super.viewDidLoad()
...
let swipeGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(onSwiped(_:)))
swipeGestureRecognizer.delegate = self
self.tableView.addGestureRecognizer(swipeGestureRecognizer)
}

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}

@objc private func onSwiped(_ gestureRecognizer: UIPanGestureRecognizer) {
if gestureRecognizer.state == .ended {
let translation = gestureRecognizer.translation(in: self.view)
guard translation.x < 0 else { return }
let width = self.tableView.bounds.width
let percentage = -translation.x / width
print("swiped left percentage:\(percentage)")
if percentage > 0.2 {
let location = gestureRecognizer.location(in: self.tableView)
if let indexPath = self.tableView.indexPathForRow(at: location) {
print("delete row: \(indexPath.row)")
self.dataSource.remove(at: indexPath.row)
self.tableView.reloadData()
}
}
}
}

Demo

swipe 20% to delete row

Swiping Allowed Only On Certain Cells

If you check whether to display edit actions or not in tableView(_: UITableView, editActionsForRowAt: IndexPath), the user experience will be sloppy because when return an empty array of actions to not show any edit actions, the cell appears as if it got swiped for a moment and then stops responding to the swipe. Instead you should check whether to display the edit actions for a cell or not, using tableview(_:UITableView,canEditRowAt:IndexPath) and then use the other function to actually display the actions when the cell is swipeable.

func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
let cell = tableView.cellForRow(at: indexPath) as! DetailsCell
if isCharacterButtonPressed == true && cell.label != currentUser.name{
return true
} else {
return false
}
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let cell = tableView.cellForRow(at: indexPath) as! DetailsCell
let detailsAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "Details") { (action , indexPath) -> Void in
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "SeeDetails") as! DetailsVC
viewController.person = cell.person
self.navigationController?.pushViewController(viewController, animated: true)
}
return [detailsAction]
}


Related Topics



Leave a reply



Submit