I am implementing a swipe to delete feature on all UITableViewCell
in my UITableView
. In the same time I would like use a custom button, and for this purpose, this tutorial came in handy: Custom edit view in UITableViewCell while swipe left. Objective-C or Swift
(I went with the 4th solution). So far, I am satisfied with my overall result as it work out just well. However, I have noticed that in my case, when swiping on the cell, the cell travel does not stop just after the hidden button is unveiled, rather is continues and it unveils some gray space. Once the cell is released, it bounces back, covering the gray space. The big question is, how do I disable this bounce effect and have the cell stop on slide just after the button is unveiled?
My problem is very similar to this one How to remove UITableViewCell swipe to delete bounce
. However, I've tried all UISwipeViewDelegate
solutions and none of them work for me.
This is my code:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
@IBOutlet weak var tableView: UITableView!
lazy var rowHeight: CGFloat = {
return 82
}()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
let nibName = UINib(nibName: "TableViewCell", bundle: nil)
tableView.register(nibName, forCellReuseIdentifier: "cell")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func numberOfSections(in tableView: UITableView) -> Int {
return 20
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
cell.makeCellWith(image: "sampleImage", userName: "userNameSample")
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return rowHeight
}
// MARK: - Cell Sections
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
view.frame = UIEdgeInsetsInsetRect(view.frame, UIEdgeInsetsMake(0, 10, 0, 10))
}
// Set the spacing between sections
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 10
}
// Make the background color show through
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
headerView.backgroundColor = UIColor.clear
return headerView
}
// MARK: - Slide to delete feature
fileprivate func whitespaceString(font: UIFont = UIFont.systemFont(ofSize: 15), width: CGFloat) -> String {
let padding: CGFloat = 20
let mutable = NSMutableString(string: "")
let attribute = [NSAttributedStringKey.font: font]
while mutable.size(withAttributes: attribute).width < width - (2 * padding) {
mutable.append(" ")
}
return mutable as String
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let whitespace = whitespaceString(width: rowHeight)
let deleteAction = UITableViewRowAction(style: .default, title: whitespace) { (action, indexPath) in
// do action on delete here
}
// create a color from pattern image and set the color as a background color of action
let view = UIView(frame: CGRect(x: 0, y: 0, width: rowHeight, height: rowHeight))
view.backgroundColor = UIColor.white
let imageSize: CGFloat = 50
let imageView: UIImageView = {
let iv = UIImageView()
let buttonImage = UIImage(named: "plusButton")
iv.image = buttonImage
return iv
}()
imageView.frame = CGRect(x: (view.frame.height - imageSize)/2,
y: (view.frame.width - imageSize)/2,
width: imageSize,
height: imageSize)
view.addSubview(imageView)
let image = view.image()
deleteAction.backgroundColor = UIColor(patternImage: image)
return [deleteAction]
}
// MARK: - Delete Object
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
fileprivate extension UIView {
func image() -> UIImage {
UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0)
guard let context = UIGraphicsGetCurrentContext() else {
return UIImage()
}
layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}