15

I see in some apps when you come to a screen with a tableview there's a short animation of the cell starting to be swiped, showing the red "swipe to delete" button (UIContextualAction button) and then it returns to normal. It is giving the user the hint: "These rows can be swiped."

Is there a way to achieve this effect? Maybe a way to programmatically start a row swipe then cancel it?

Mark Moeykens
  • 15,915
  • 6
  • 63
  • 62

2 Answers2

18

Swift Solution

Well, about 1.5 years later I finally came up with a solution.

Step 1 - Cell UI Setup

I set up my custom table view cell like this: UI Work

  • A and B represent the swipe action colors.
  • C is the UIView that I will animate side-to-side.

Step 2 - Add Animation to Cell

func animateSwipeHint() {
    slideInFromRight()
}

private func slideInFromRight() {
    UIView.animate(withDuration: 0.5, delay: 0.3, options: [.curveEaseOut], animations: {
        self.cellBackgroundView.transform = CGAffineTransform(translationX: -self.swipeHintDistance, y: 0)
        self.cellBackgroundView.layer.cornerRadius = 10
    }) { (success) in
        UIView.animate(withDuration: 0.2, delay: 0, options: [.curveLinear], animations: {
            self.cellBackgroundView.transform = .identity
        }, completion: { (success) in
            // Slide from left if you have leading swipe actions
            self.slideInFromLeft()
        })
    }
}

private func slideInFromLeft() {
    UIView.animate(withDuration: 0.5, delay: 0, options: [.curveEaseOut], animations: {
        self.cellBackgroundView.transform = CGAffineTransform(translationX: self.swipeHintDistance, y: 0)
    }) { (success) in
        UIView.animate(withDuration: 0.2, delay: 0, options: [.curveLinear], animations: {
            self.cellBackgroundView.transform = .identity
        })
    }
}

Step 3 - Trigger the Animation

In the viewDidLoad of the view controller that has the table view, I have this code:

if self.tableView.visibleCells.count > 0 {
    let cell = self.tableView.visibleCells[0] as! TableViewCell
    cell.animateSwipeHint()
}

Example:

Example Animation

Video Solution

I created a video if you'd like a more in-depth walkthrough of this solution: https://youtu.be/oAGoFd_GrxE

Mark Moeykens
  • 15,915
  • 6
  • 63
  • 62
3

I have a piece of code that I saw long time ago to animate a view. Since our UITableViewCell is also a view, we can use it :) You just need to get your visible cell to animate, like so:

if let visibleCell = self.tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as? CustomCell {
        print("Started animation...")
        let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        animation.duration = 0.6
        animation.values = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0 ]
        visibleCell.layer.add(animation, forKey: "shake")
    }

Let me know if this helps. Tested it.

EDIT:

Animating your UITableView to let the user see that they can swipe on a cell is pretty easy, try it like so:

    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
        self.tableView.setEditing(true, animated: true)
        DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
            self.tableView.setEditing(false, animated: true)
        }
    }

HOWEVER, if you want to swipe programmatically your cell to show your custom row actions, (I've been researching this for an hour), you can only achieve this, as far as I know, by using method swizzling. See this SO answer: http://codejaxy.com/q/186524/ios-swift-uitableview-how-to-present-uitableviewrowactions-from-pressing-a-button

Glenn Posadas
  • 12,555
  • 6
  • 54
  • 95
  • Thanks, @Glenn, while this does shake the cell's content view side to side it does not expose the buttons (UIContextActions). I'll modify my question to clarify. – Mark Moeykens Oct 23 '17 at 13:27
  • Thanks, @Glenn, but when I try that second code sample all it does it show the round delete buttons on the right side of the cells. The swizzling answer looks interesting but I just wanted to see if there were any publicly exposed API-oriented solutions. – Mark Moeykens Oct 25 '17 at 04:28
  • Thanks, this is pretty much simple and good catch on inbuilt methods of UITableView – Rakshitha Muranga Rodrigo Feb 15 '21 at 14:19