How to Implement iOS library animation-Part 1 (Part 1)
Welcome back to the iOS library animation series tutorial! In the first part, we learned how to create two custom collection view layout and use a shadow layer on the book page to make our App more stereoscopic and realistic.
In this section, we will learn how to create a custom transfer animation and open a book with a pinch gesture.
Note: Thanks to Attila Heged üs for creating the sample program for this tutorial.
Start
The previous sections of this tutorial are based on. If you have not read the first part, or want to start from a new project, you can download the complete sample program in the previous section.
Open the project in Xcode. Now you can select a book to read and slide from the right side to flip the pages. In this case, the transfer animation uses the animation effect provided by UINavigationController. After learning this tutorial, We will customize the animation effect, as shown in:
This animation will smooth the transition between the "open book" and "" one by one in a more natural way, which will benefit the user's favor. Let's get started!
Create a custom navigation Controller
To create a custom push animation and pop animation, we must create a custom navigation controller and implement the UINavigationControllerDelegate protocol.
Right-click the App folder (or press ctrl + left) and click New File. Select the iOSSourceCocoa Touch Class template and set the Class name to CustomNavigationController. Let it inherit from UINavigationController and set the language to Swift. Click Next and Create.
Open CustomNavigationController. swift and edit the following content:
import UIKit
class CustomNavigationController: UINavigationController, UINavigationControllerDelegate {
override func viewDidLoad () {
super.viewDidLoad ()
//1
delegate = self
}
//2
func navigationController (navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController)-> UIViewControllerAnimatedTransitioning? {
if operation == .Push {
return nil
}
if operation == .Pop {
return nil
}
return nil
}
}
The above codes are explained as follows:
In the viewDidLoad method, set the CustomNavigationController's delegate property to itself. The navigationController (_: animationControllerForOperation: fromViewController: toViewController :) method belongs to the UINavigationControllerDelegate protocol. This method is called when push or pop navigation occurs between two View Controllers. You can return the respective Transition object for push navigation and pop navigation in this method. Currently we all return nil, which indicates that we will use the standard Transition built into UINavigationController. Later we will replace it with our own Transition object.
Now that we have our own Navigation Controller class, next replace the default UINavigationController with our CustomNavigationController in the storyboard.
Open Main.storyboard, select the Navigation Controller object in the object window on the left of the storyboard editor, open the Identity window, and under Custom Class, modify the Class from UINavigationController to CustomNavigationController, as shown:
Compile and run, nothing has changed. This is because we still return nil in the delegate method, so the standard Transition built into UINavigationController is still used.
Create custom navigation animation
The most interesting part is here-create our custom Transition object!:]
To customize the Transition class, we must implement the UIViewControllerAnimatedTransitioning protocol, the most important of which are these methods:
transitionDuration: must be implemented. This method returns the duration of an animation, making the playback time of the two animations the same (or different). animateTransition: Must be realized. This method is responsible for providing two controllers participating in the animation: a to controller and a from controller. Most of Transiton's work is done in this method. animationEnded: Optional method. This method is mainly used to notify you when the animation is complete. We can perform the necessary cleanup actions in this method. Create a custom Transition class
Right-click (or ctrl + left-click) on the App folder, and then click New File. Select the iOSSourceCoca Touch Class template, set the class name to BookOpeningTransition, inherit NSObject, language Swift. Then click Next, Create.
Open BookOpeningTransition.swift and edit the code as follows:
import UIKit
//1
class BookOpeningTransition: NSObject, UIViewControllerAnimatedTransitioning {
// MARK: Stored properties
var transforms = [UICollectionViewCell: CATransform3D] () // 2
var toViewBackgroundColor: UIColor? // 3
var isPush = true // 4
// 5
// MARK: UIViewControllerAnimatedTransitioning
func transitionDuration (transitionContext: UIViewControllerContextTransitioning)-> NSTimeInterval {
return 1
}
func animateTransition (transitionContext: UIViewControllerContextTransitioning) {
}
}
The above codes correspond to the numbers in the comments, and are explained as follows:
Declare the BookOpeningTransition class to implement the UIViewControllerAnimatedTransitioning protocol. Declare a transforms dictionary, the key stores UICollectionViewCell, and the value stores the corresponding CATransiform3D. This dictionary saves the page turning animation of all cells after the book is opened. Specify the background color of the to view controller, it will make the fade-in and fade-out animation look more clear. The boolean isPush is used to identify whether the current animation is Push animation or Pop animation. Add the UIViewControllerAnimatedTransitioning protocol method that must be implemented to prevent compilation errors from appearing. We will implement these methods later.
Define the required variables, the next step is to implement the protocol method.
The first is the transitionDuration (_ :) method:
if isPush {
return 1
} else {
return 1
}
The transitionDuration (_ :) method returns the duration of the animation. Here, whether it is Push animation or Pop animation, we are set to 1 second. Through this method we can easily change the duration of Push animation or Pop animation.
Then, is the second protocol method-animateTransition-this is the core part! :] We will introduce this method into two parts:
Implement a helper method for creating the Transition object needed for Push animation. Implement a helper method for creating the Transition object needed for Pop animation. Create Push animation
Recall how you opened a book in your life:
Although it seems complicated, we only need to consider two states, and let the animateWithDuration method of UIView perform different processing according to these two states:
State 1, the book is in the closed state. State 2, the book is open; this is what we implemented in the first part of the tutorial.
First, before implementing the animateTransition (: _) protocol method, let's implement several helper methods.
Still in BookOpeningTransition.swift, write the following method:
// MARK: Helper Methods
func makePerspectiveTransform ()-> CATransform3D {
var transform = CATransform3DIdentity
transform.m34 = 1.0 / -2000
return transform
}
This method returns a Transform object, and adds a little sense of stereo on the z axis. We will use this method when playing animations.
State 1-Closed Book
After the makePerspectiveTransform method, implement the following method:
func closePageCell (cell: BookPageCell) {
// 1
var transform = self.makePerspectiveTransform ()
// 2
if cell.layer.anchorPoint.x == 0 {
// 3
transform = CATransform3DRotate (transform, CGFloat (0), 0, 1, 0)
// 4
transform = CATransform3DTranslate (transform, -0.7 * cell.layer.bounds.width / 2, 0, 0)
// 5
transform = CATransform3DScale (transform, 0.7, 0.7, 1)
}
// 6
else {
// 7
transform = CATransform3DRotate (transform, CGFloat (-M_PI), 0, 1, 0)
// 8
transform = CATransform3DTranslate (transform, 0.7 * cell.layer.bounds.width / 2, 0, 0)
// 9
transform = CATransform3DScale (transform, 0.7, 0.7, 1)
}
// 10
cell.layer.transform = transform
}
Recall that BookViewController, which is a CollectionView, represents a page in the book. We align each page with the spine of the book and rotate it around the y-axis to achieve the page turning effect. First, the book is closed (closed). This method lays down each cell (that is, the book page) and places it under the cover.
This is the animation running effect:
The above code is explained as follows:
Use the helper method created earlier to generate a Transform object. Determine whether the cell is the right page. If it is, set its angle to 0, that is, place it horizontally. Move it under the cover and align it in the center. Scale it to 70%. Remember when we scaled the cover to 70%? Here is the same meaning. If the cell is not the right page, it is the left page. Set the angle of the left page to 180 degrees. To lay it horizontally, we need to turn it to the right of the spine. Place it under the cover and align it in the center. Zoom by 70%. Finally, assign the transform attribute of the cell.
Add the following method after the above method:
func setStartPositionForPush (fromVC: BooksViewController, toVC: BookViewController) {
// 1
toViewBackgroundColor = fromVC.collectionView? .backgroundColor
toVC.collectionView? .backgroundColor = nil
//2
fromVC.selectedCell () ?. alpha = 0
// 3
for cell in toVC.collectionView! .visibleCells () as! [BookPageCell] {
// 4
transforms [cell] = cell.layer.transform
// 5
closePageCell (cell)
cell.updateShadowLayer ()
// 6
if let indexPath = toVC.collectionView? .indexPathForCell (cell) {
if indexPath.row == 0 {
cell.shadowLayer.opacity = 0
}
}
}
}
The setStartPositionForPush (_: toVC :) method creates a Transition of state 1. This animation involves two ViewControllers:
fromVC, type BooksViewController, used to scroll through the book list.
toVC, BookViewController type, allows you to flip through the selected book.
The above code is explained as follows:
Save the background color of CellView of BooksViewController, and then set the background color of BookViewController's Collection View to nil Hide cover. ToVC will now handle the display of the cover image. Traverse all pages in the book. Save the current Transform of each page to the transforms dictionary. Since the book was closed at the beginning, we converted the page to the closed state and then updated the shadow layer. Finally, ignore the shadow of the cover image.