Action Sheet Follow-Up

This article uses Swift 1.0.

I received a useful feedback (thanks Peter and Krzysztof!) to my last article and decided to try to generalize that animation into a reusable component. Previously, the code was highly coupled between the view and view controller, so it would be hard to use in different scenarios. I moved the logic to UIView subclass named BendableView, which is going be responsible for bending its edges during animations affecting its position.

The library utilizes the same trick as shown in the previous article:

  • BendableView contains an internal spring animation used to calculate offsets of edges' centers on every frame, and
  • CAShapeLayer with a suitable path makes it look like it's bending (CAShapeLayer replaced drawing with drawInRect:)

BendableView exposes a small API:

var damping: CGFloat
var initialSpringVelocity: CGFloat
var fillColor: UIColor

which is quite easy to use:

let bv = BendableView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

// bending setup
bv.fillColor = UIColor.redColor()
bv.damping = 0.7 // used to animate the view's edges
bv.initialSpringVelocity = 0.8 // used to animate the view's edges

    delay: 0,
    usingSpringWithDamping: 0.9,
    initialSpringVelocity: 0.9,
    options: .BeginFromCurrentState | .AllowUserInteraction,
    animations: {
      bv.frame.origin = CGPoint(x: 200, y: 300)
      bv.frame.size = CGSize(width: 150, height: 150)
    }, completion: nil

To change the bending behavior, damping and initialSpringVelocity properties have to be adjusted. These two properties could be removed – or replaced by some higher-level setting – but Apple keeps CASpringAnimation private (rdar://17496711). Therefore, officially it's not possible to access damping and initial velocity parameters of animations created with +animateWithDuration:delay:usingSpringWithDamping: initialSpringVelocity:options:animations:completion:.

The path has to be recalculated on each frame, so it could impact the performance. I created a looped animation and profiled it on iPad 3 running iOS 8 beta 2. It performed flawlessly.

The library is available on GitHub and as always I welcome any feedback. Finally, here it is in action: