iosobjective-cswiftcabasicanimationcatransition

Animating Views and subviews in sequence


Im struck with Animation. I would like to animate in below sequence as shown in picture.

Please click here for Image

All are views i.e., outerView, dot1, dot2, dot3 . I've implemented code to animate dots but need your help to animate outerview and adding everything in sequence

 let transition = CATransition()
    transition.duration = 2;
    transition.type = kCATransitionPush;
    transition.subtype = kCATransitionFromLeft;
    transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault)
    transition.speed = 1.0

    dot3?.layer.add(transition, forKey: nil)
    transition.beginTime = CACurrentMediaTime() + 0.11
    dot2?.layer.add(transition, forKey: nil)
    transition.beginTime = CACurrentMediaTime() + 0.22
    dot1?.layer.add(transition, forKey: nil)

Please help me animating in sequence - outerView starting, dots and closing outerView like shown


Solution

  • You're on the right path, except obviously there will be a lot more animations than the few that you've shown in the snippet. There's no reason why you can't continue building this animation using the CAAnimation classes, but I suspect that using the newer UIViewPropertyAnimator classes (will need to target iOS10) will be useful because they allow you to 'scrub' the steps in the animation which will be useful debugging. Here's a good intro: dzone.com/articles/ios-10-day-by-day-uiviewpropertyanimator

    Expanding on this comment to a proper answer...

    Using animateWithKeyframes is a pretty decent solution to create this animation in code. Here's a snippet of what this could look like:

    let capsule: UIView // ... the container view
    let capsuleDots [UIView] //... the three dots
    let capsuleFrameWide, capsuleFrameNarrow: CGRect //.. frames for the capsule
    let offstageLeft, offstageRight: CGAffineTransform // transforms to move dots to left or right
    
    let animator = UIViewPropertyAnimator(duration: 2, curve: .easeIn)
    
    // the actual animation occurs in 4 steps
    animator.addAnimations {
    
        UIView.animateKeyframes(withDuration: 2, delay: 0, options: [.calculationModeLinear], animations: {
    
            // step 1: make the capsule grow to large size
            UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.1) {
                capsule.bounds = capsuleFrameWide
            }
    
            // step 2: move the dots to their default positions, and fade in
            UIView.addKeyframe(withRelativeStartTime: 0.1, relativeDuration: 0.1) {
                capsuleDots.forEach({ dot in
                    dot.transform = .identity
                    dot.alpha = 1.0
                })
            }
    
            // step 3: fade out dots and translate to the right
            UIView.addKeyframe(withRelativeStartTime: 0.8, relativeDuration: 0.1) {
                capsuleDots.forEach({ dot in
                    dot.alpha = 0.0
                    dot.transform = offstageRight
    
                })
            }
    
            // step4: make capsure move to narrow width
            UIView.addKeyframe(withRelativeStartTime: 0.9, relativeDuration: 0.1) {
                capsule.bounds = capsuleFrameNarrow
            }
        })
    }
    

    Wrapping the keyframes in a UIViewPropertyAnimator makes it easy to scrub the animation (among other things).

    enter image description here

    In case it's useful for anyone, I've pushed a small project to GitHub that allows you to jump in an explore/refine/debug animations with UIViewPropertyAnimator. It includes boilerplate for connecting the UISlider to the animation so all you have to focus on is the animation itself.

    This is all for debugging the animation, for production of course you'll probably want to remove hard coded sizes so it can be potentially reused at different scales etc.