- Notifications
You must be signed in to change notification settings - Fork0
arnoldlee850807/Rebuild-App-Store-Transition
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Check the tutorial here
https://medium.com/@kannolee/rebuilding-appstore-card-like-transition-84a73fc7139b
Recreate the card like transition Apple made for the App Store "Today" category. By using collection view + pan gesture recognizer.This project is based on Swift 4.
Here's what it'll look like
Simply copy and paste TransitionClone.swift to your project, and add UIViewControllerTransitioningDelegate to the Class you're going to use.
Then add the two function above. Here I created an enum called transitionMode for the purpose to tell the code what state of transition we are in, if we’re going to Present than set it to “present”, if dismiss than set it to “dismiss”, simple as that.
let transition = TransitionClone()func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { transition.transitionMode = .present return transition}func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { transition.transitionMode = .dismiss return transition}Don't forget to set the starting frame and ending frame, for example:
transition.startingFrame = CGRect(x: a.minX+15, y: a.minY+15, width: 375 / 414 * view.frame.width - 30, height: 408 / 736 * view.frame.height - 30)transition.destinationFrame = CGRect(x: 0, y: 0, width: view.frame.width, height: cell.myImage.frame.height * view.frame.width / cell.myImage.frame.width)For the Pan Gesture, we’re going to use UIPanGestureRecognizer, which includes states like began, changed, ended, etc. It’ll give us the convenience to manipulate the animation ongoing percentage. You’ll get what I’m talking about very soon, but now let’s just add the above code to your destination view controller.
import UIKit.UIGestureRecognizerSubclassclass InstantPanGestureRecognizer: UIPanGestureRecognizer {override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) { if (self.state == UIGestureRecognizerState.began) { return } super.touchesBegan(touches, with: event) self.state = UIGestureRecognizerState.began }}Create the shrinking animation when draging on the Image, notice that we’re not going to use UIView.animate here because UIViewPropertyAnimator has the advantage to pause and resume the animation. You might be thinking why do we need to pause and resume the animation? Because we want the animation to interact with user’s finger! Which in other word to ““follow”” the finger.
var animator = UIViewPropertyAnimator()func shrinkAnimation(){ animator = UIViewPropertyAnimator(duration: 1.0, curve: .easeOut, animations: { self.view.transform = CGAffineTransform(scaleX: 0.85, y: 0.85) self.view.layer.cornerRadius = 15 }) animator.startAnimation()}Create a gesture recognizer and add to a UIView, I added on a button but it's ok to add it on the imageView
let recognizer = InstantPanGestureRecognizer(target: self, action: #selector(panRecognizer))dismissButton.addGestureRecognizer(recognizer)Create the panRecognizer, and it should work fine. Here’s what do the magic trick, by pausing the animation immediately after starting, we’re now in case .changed, we then track the vertical distance the finger drag from it’s initial place(if you want to track horizontal distance, just change translation.y ⇢ translation.x). Than add it to the current animation process(animator.fractionComplete). For a single tap recognition it’s even easier, there’s no need to add another tap recognizer. Just add an if statement in recognizer.state = ended see the code above :)
var animationProgress: CGFloat = 0.0@objc func panRecognizer(recognizer: UIPanGestureRecognizer){ let translation = recognizer.translation(in: dismissButton) switch recognizer.state{ case .began: shrinkAnimation() animationProgress = animator.fractionComplete // Pause after Start enable User to interact with the animation animator.pauseAnimation() case .changed: // translation.y = the distance finger drag on screen let fraction = translation.y / 100 // fractionComplete the percentage of animation progress animator.fractionComplete = fraction + animationProgress // when animation progress > 99%, stop and start the dismiss transition if animator.fractionComplete > 0.99{ animator.stopAnimation(true) dismiss(animated: true, completion: nil) } case .ended: // when tap on the screen animator.fractionComplete = 0 if animator.fractionComplete == 0{ animator.stopAnimation(true) dismiss(animated: true, completion: nil) } // when animator.fractionComplete < 99 % and release finger, automative rebounce to the initial state else{ // rebounce effect animator.isReversed = true animator.continueAnimation(withTimingParameters: nil, durationFactor: 0) } default: break }}About
Topics
Resources
Uh oh!
There was an error while loading.Please reload this page.
