Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to delete UITableViewCell with swipe-to-dismiss with fade effect and no red delete button?

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:

enter image description here

like image 719
rgoncalv Avatar asked Jan 27 '18 14:01

rgoncalv


People also ask

How to delete UITableViewCell in swift?

When you want to handle deleting, you have to do three things: first, check that it's a delete that's happening and not an insert (this is down to how you use the UI); second, delete the item from the data source you used to build the table; and third, call deleteRows(at:) on your table view.

How do you customize swipe edit buttons in Uitableview?

As of iOS 8.0 there's an easy way to customize the list of buttons that appear when the user swipes from right to left: editActionsForRowAt . Return an array of UITableViewRowAction objects that have titles and styles (and also background colors if you want to customize their appearance), and iOS does the rest.


2 Answers

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
    }
 }
}

=============================

like image 138
McDonal_11 Avatar answered Oct 26 '22 13:10

McDonal_11


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.

like image 43
Latenec Avatar answered Oct 26 '22 14:10

Latenec