rgoncalv
rgoncalv

Reputation: 6035

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

Upvotes: 8

Views: 1738

Answers (6)

Latenec
Latenec

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

J. Koush
J. Koush

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

McDonal_11
McDonal_11

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

Vishnu
Vishnu

Reputation: 56

You can animate the content view and on completion of animation you can delete the cell

Upvotes: 0

Inder Jagdeo
Inder Jagdeo

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

Ganesh Manickam
Ganesh Manickam

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

Related Questions