Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move UITableViewCell back and forth to show it can be swiped?

Tags:

ios

swift

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?

like image 421
Mark Moeykens Avatar asked Oct 23 '17 03:10

Mark Moeykens


2 Answers

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

like image 54
Mark Moeykens Avatar answered Oct 18 '22 22:10

Mark Moeykens


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

like image 3
Glenn Posadas Avatar answered Oct 18 '22 21:10

Glenn Posadas