How to make a UITableViewCell shake from the left side to the right side?
I want the user to know that "this action isn't possible"!
How to make a UITableViewCell shake from the left side to the right side?
I want the user to know that "this action isn't possible"!
Swift 5. I found this solution.
1.Add this extensions
import UIKit
extension UIView {
func shake() {
let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
animation.duration = 0.6
animation.values = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0 ]
layer.add(animation, forKey: "shake")
}
}
2. In TableViewCell
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
if highlighted {
if lockedState {
shakedView.shake()
}
}
}
I created a protocol based on the answer of @oyalhi with Swift 4:
protocol Shackable { }
extension Shackable where Self: UIView {
func shake(duration: CFTimeInterval = 0.3, pathLength: CGFloat = 15) {
let position = self.center
let path = UIBezierPath()
path.move(to: CGPoint(x: position.x, y: position.y))
path.addLine(to: CGPoint(x: position.x - pathLength, y: position.y))
path.addLine(to: CGPoint(x: position.x + pathLength, y: position.y))
path.addLine(to: CGPoint(x: position.x - pathLength, y: position.y))
path.addLine(to: CGPoint(x: position.x + pathLength, y: position.y))
path.addLine(to: CGPoint(x: position.x, y: position.y))
let positionAnimation = CAKeyframeAnimation(keyPath: "position")
positionAnimation.path = path.cgPath
positionAnimation.duration = duration
positionAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
CATransaction.begin()
self.layer.add(positionAnimation, forKey: nil)
CATransaction.commit()
}
}
Here is the Swift 4 version of oyalhi’s protocol:
import UIKit
extension UITableViewCell {
func shake(duration: CFTimeInterval = 0.3, pathLength: CGFloat = 15) {
let position: CGPoint = self.center
let path: UIBezierPath = UIBezierPath()
path.move(to: CGPoint(x: position.x, y: position.y))
path.addLine(to: CGPoint(x: position.x-pathLength, y: position.y))
path.addLine(to: CGPoint(x: position.x+pathLength, y: position.y))
path.addLine(to: CGPoint(x: position.x-pathLength, y: position.y))
path.addLine(to: CGPoint(x: position.x+pathLength, y: position.y))
path.addLine(to: CGPoint(x: position.x, y: position.y))
let positionAnimation = CAKeyframeAnimation(keyPath: "position")
positionAnimation.path = path.cgPath
positionAnimation.duration = duration
positionAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
CATransaction.begin()
self.layer.add(positionAnimation, forKey: nil)
CATransaction.commit()
}
}
Thank you Hans One!. And here it is in Swift and in extension form to UITableViewCell
with duration and path length selectable.
import UIKit
import QuartzCore
extension UITableViewCell {
func shake(duration: CFTimeInterval = 0.3, pathLength: CGFloat = 15) {
let position: CGPoint = self.center
let path: UIBezierPath = UIBezierPath()
path.moveToPoint(CGPointMake(position.x, position.y))
path.addLineToPoint(CGPointMake(position.x-pathLength, position.y))
path.addLineToPoint(CGPointMake(position.x+pathLength, position.y))
path.addLineToPoint(CGPointMake(position.x-pathLength, position.y))
path.addLineToPoint(CGPointMake(position.x+pathLength, position.y))
path.addLineToPoint(CGPointMake(position.x, position.y))
let positionAnimation = CAKeyframeAnimation(keyPath: "position")
positionAnimation.path = path.CGPath
positionAnimation.duration = duration
positionAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
CATransaction.begin()
self.layer.addAnimation(positionAnimation, forKey: nil)
CATransaction.commit()
}
}
This is my solution:
Have fun!