Reputation: 6035
After looking into a myriad of StackOverflow posts, nothing really answers how to delete a UITableViewCell
with swipe-to-dismiss while fading and without the red delete button.
My Tableviewcell looks like a card, so the red frame of the delete button breaks the sense of continuity and elevation of these cells with card shapes.
Here is the code I am currently using to delete, which does not fade despite the .fade
on the UITableViewRowAnimation
.
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .none
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
self.pastOrders.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
Here's a screenshot of the behavior I am trying to achieve:
Upvotes: 8
Views: 1738
Reputation: 418
I guess SwipeCellKit pod is an option as well to do swiping without delete button, so please check out this link: https://github.com/SwipeCellKit/SwipeCellKit.
There is all documentation how you can customize it and if you can see the Destructive gif on the link, it is what you wanted, however you have to make it custom so there is no other buttons nor the delete button as well.
I hope it helped you somehow.
Upvotes: 1
Reputation: 1068
You can add a swipe gesture on the content of your custom cell, when the swipe animation is over you call a delegate method to the ViewController in which it will update the data array delete the tableView row and reload the tableView.
Upvotes: 0
Reputation: 4075
Output 3
//TO CHANGE "DELETE" TITLE COLOR
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let toDelete = UITableViewRowAction(style: .normal, title: "") { (action, indexPath) in
print("\n\n Delete item at indexPathDelete item at indexPath")
}
let deleteTextImg = swipeCellButtons(labelText: "Delete", textColor: UIColor.darkGray, alphaVal: 1.0)
toDelete.backgroundColor = UIColor(patternImage: deleteTextImg)
return [toDelete]
}
func swipeCellButtons(labelText : String, textColor: UIColor, alphaVal: CGFloat) -> UIImage
{
let commonWid : CGFloat = 40
let commonHei : CGFloat = 70 // ROW HEIGHT
let label = UILabel(frame: CGRect(x: 0, y: 0, width: commonWid, height: commonHei))
label.text = labelText
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 11)
label.textColor = textColor.withAlphaComponent(alphaVal)
UIGraphicsBeginImageContextWithOptions(CGSize(width: self.view.frame.width, height: commonHei), false, UIScreen.main.scale)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(UIColor.clear.cgColor) // YOU CAN GIVE YOUR BGCOLOR FOR DELETE BUTTON
context!.fill(CGRect(x: 0, y: 0, width: (self.view.frame.width) / 3, height: commonHei))
label.layer.render(in: context!)
//If you want to add image instead of text, uncomment below lines.
//Then, comment this "label.layer.render(in: context!)" line
//var img: UIImage = UIImage(named: "deleteIcon")!
//img.draw(in: CGRect(x: 0, y: 0, width: 30, height: 30))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
Output 2:
// INSIDE CELL FOR ROW AT INDEXPATH
// COMMENT THIS LINE
//cell.addGestureRecognizer(swipeGesture)
// CELL FADE WILL NOT WORK HERE
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let toDelete = UITableViewRowAction(style: .normal, title: " ") { (action, indexPath) in
print("\n\n Delete item at indexPathDelete item at indexPath")
}
toDelete.backgroundColor = .white
return [toDelete]
}
Output 1:
// GLOBAL DECLARATION
var gotCell : DefaultTableViewCell?
var alphaValue : CGFloat = 1.0
var deletingRowIndPath = IndexPath()
// INSIDE CELL FOR ROW AT INDEXPATH
//let cell = tableView.dequeueReusableCell(withIdentifier: "default", for: indexPath) as! DefaultTableViewCell
let cell = DefaultTableViewCell() // Add this line and comment above line. The issue is `dequeuingreusingcell`. In this method, it will stop dequeuing. But, we have to customise `UITableViewCell` in coding.
let swipeGesture = UIPanGestureRecognizer(target: self, action: #selector(handleSwipe))
swipeGesture.delegate = self
cell.addGestureRecognizer(swipeGesture)
func handleSwipe(panGesture: UIPanGestureRecognizer) {
if panGesture.state == UIGestureRecognizerState.began {
let cellPosition = panGesture.view?.convert(CGPoint.zero, to: defTblVw)
let indPath = defTblVw.indexPathForRow(at: cellPosition!)
deletingRowIndPath = indPath!
gotCell = defTblVw.cellForRow(at: indPath!) as! DefaultTableViewCell
}
if panGesture.state == UIGestureRecognizerState.changed
{
let isLeftMoving = panGesture.isLeft(theViewYouArePassing: (gotCell)!)
if isLeftMoving == true
{
self.gotCell?.alpha = self.alphaValue
self.gotCell?.frame.origin.x = (self.gotCell?.frame.origin.x)! - 2.5
self.view.layoutIfNeeded()
self.alphaValue = self.alphaValue - 0.005
}
else // ADD THIS ELSE CASE
{
self.alphaValue = 1.0
self.gotCell?.alpha = 1.0
UIView.animate(withDuration: 0.8, animations: {
self.gotCell?.frame.origin.x = 0
self.view.layoutIfNeeded()
}) { (value) in
}
}
}
if panGesture.state == UIGestureRecognizerState.ended
{
self.alphaValue = 1.0
if (self.gotCell?.frame.origin.x)! < CGFloat(-(defTblVw.frame.size.width - 90))
{
myArr.remove(at: (deletingRowIndPath.row))
defTblVw.beginUpdates()
defTblVw.deleteRows(at: [deletingRowIndPath], with: UITableViewRowAnimation.fade)
defTblVw.endUpdates()
}
else
{
UIView.animate(withDuration: 0.8, animations: {
self.gotCell?.alpha = 1.0
self.gotCell?.frame.origin.x = 0
self.view.layoutIfNeeded()
}) { (value) in
}
}
}
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
extension UIPanGestureRecognizer {
func isLeft(theViewYouArePassing: UIView) -> Bool {
let velocityVal : CGPoint = velocity(in: theViewYouArePassing)
if velocityVal.x >= 0 {
return false
}
else
{
print("Gesture went other")
return true
}
}
}
=============================
Upvotes: 2
Reputation: 56
You can animate the content view and on completion of animation you can delete the cell
Upvotes: 0
Reputation: 229
Try this code.
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let toDelete = UITableViewRowAction(style: .normal, title: " ") { (action, indexPath) in
self.rows.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
toDelete.backgroundColor = .white
return [toDelete]
}
Hope it would help you.
Upvotes: 0
Reputation: 2139
You can use this library with .exit
mode
and In your cellForRow
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! SwipyCell //User You cell identifier and class of cell here
let checkView = viewWithImageName("check") //Use some white dummy image
cell.addSwipeTrigger(forState: .state(0, .left), withMode: .exit, swipeView: checkView, swipeColor: tableView.backgroundView?.backgroundColor, completion: { cell, trigger, state, mode in
print("Did swipe \"Checkmark\" cell")
})
return cell
}
Hope this will help you
Upvotes: 0