📜 ⬆️ ⬇️

Guide to animated display of views in a table on Swift

The standard UITableView is a powerful yet flexible way to present data in your applications; chances are that most of the applications you create will use the table view in one form or another. However, there is a drawback that without some level of customization, applications will look pale and blend in with thousands of similar ones. In order to avoid “boring” tables, you can add a few suitable animated images that “animate” the application. You may have seen this in the Google+ app, where cells in the table literally fly around the screen along with cool animation. If you did not pay attention to it, you can download it here (for free)! It may also be useful and interesting to get acquainted with the design guidelines ( design guidelines ), which Google released at the 2014 I / O conference. It contains many tips and examples on how to effectively and correctly use animation in your applications.


In this article, the Swift programming language for improvement will be used for an existing application, while scrolling the table cells and moving the image vertically. It also describes how to convert to UIKit, and their convenient use in order to avoid overloading too many actions that occur simultaneously on the screen. You will receive tips on how to organize the program code so that tasks are simple and straightforward, and your main controller simple.

First, you should familiarize yourself with how to work with UITableView and with the basic elements in Swift. If you need to familiarize yourself with this, then you can start familiarizing yourself with the Swift Tutorial series, which will teach you the basics of working in the Swift language regarding applications on a table view.
')
Let's start.

Download the starter project and open it in Xcode 6. You will see a simple project description (UITableViewController) subclass (MainViewController) and setting UITableViewCell (CardTableViewCell) to display developers. You will also find an example of the Member class, which describes all the information about a team member and knows how to extract this information from the JSON file that is located inside our application.

Compile and run the project. You will see the following:

image

Excellent design, ready to give it a special color and improvement

The application is ready to use, but it could contain a little more individualism, so to say have its own "flavor". This is your job; Use some Core Animation tricks to liven up the data cell.

Determine the easiest possible way to animate.

To get the basic structure of the application, start by creating a simple helper class. Navigate to File \ New \ File ... and select the iOS \ Source \ Swift File type for an empty Swift file. Click Next, name the file TipInCellAnimator.swift and then click Create.

Replace the contents of the file with the following code:

import UIKit class TipInCellAnimator { // placeholder for things to come -- only fades in for now class func animate(cell:UITableViewCell) { if let view = cell.contentView { view.layer.opacity = 0.1 UIView.animateWithDuration(1.4) { view.layer.opacity = 1 } } } } 


This simple class contains an algorithm that takes a cell with data, accesses its content (contentView), and sets the initial transparency of the layer to 0.1. Then, after 1.4 seconds, the program code in the closing expression converts the layer's transparency back to 1.0.

Note: an expression in Swift is simply a block of code that can also span external variables. For example, {} is a simple expression. Functions denoted as func are examples of named expressions. In Swift, you can open functions within other functions.

If you pass an expression as the last argument to a function, you can use the special syntax trailing closure (final expression) and move the expression out of the function call.

Read more about expressions in the Swift Programming Language book or read the article about the history of expressions (rich history of closures) in Wikipedia.

When the animation code is ready, you need to configure the table so that you can start a new animation when a cell with data appears.

Running animation

To start the animation, open the MainViewController.swift file and add the following method:

 override func tableView(tableView: UITableView!, willDisplayCell cell: UITableViewCell!, forRowAtIndexPath indexPath: NSIndexPath!) { TipInCellAnimator.animate(cell) } 


This algorithm is indicated in the UITableViewDelegate protocol and is called before the cell appears on the screen. Then the algorithm of the class TipInCellAnimator is called for each cell in order to start the animation.

Compile and run the application. Scroll through the table with information and see how the cell slowly disappears:

image

Rotation effect

Let's make our application even more attractive, add rotation. This works in the same way as a pop-up animation, however you indicate both the beginning and the end of the transformations.

Open the TipInCellAnimator.swift file and replace the content with the following:

 import UIKit import QuartzCore // 1 class TipInCellAnimator { class func animate(cell:UITableViewCell) { if let view = cell.contentView { let rotationDegrees: CGFloat = -15.0 let rotationRadians: CGFloat = rotationDegrees * (CGFloat(M_PI)/180.0) let offset = CGPointMake(-20, -20) var startTransform = CATransform3DIdentity // 2 startTransform = CATransform3DRotate(CATransform3DIdentity, rotationRadians, 0.0, 0.0, 1.0) // 3 startTransform = CATransform3DTranslate(startTransform, offset.x, offset.y, 0.0) // 4 // 5 view.layer.transform = startTransform view.layer.opacity = 0.8 // 6 UIView.animateWithDuration(0.4) { view.layer.transform = CATransform3DIdentity view.layer.opacity = 1 } } } } 


This time the movement will be faster (0.4 seconds), floating more convenient and you get an interesting rotation effect. The key to the above animation determines the startTransform matrix, which brings the cell back to its original position. Let's figure out how this happens:

1. This class requires that QuartzCore be imported, as it uses key animated transformations.
2. Start by recognizing a transform, which is an arithmetic expression for a “dummy operation.” This is the default image conversion.
3. Go to CATransform3DRotate to get a rotation of 15 degrees, where a negative sign indicates counterclockwise rotation. The movement is carried out around the axes 0.0, 0.0, 1.0 and represents the vertical axis z, where x = 0, y = 0 and z = 1.
4. The use of rotation alone is insufficient, as the table / graph rotates relative to its center. In order to make a flip effect from an angle, add a shift or offset, where negative values ​​indicate moving up and to the left.
5. Set the conversion result as the original view.
6. Move the image and return the original values.

Please note that you can create a final transformation, as shown in the image below:
image

Note: An arbitrary chain of transformations may ultimately be represented by a single matrix. If you studied matrix algebra in school, then remember the effect of multiplication of matrices. Each step multiplies the new change until you reach the final matrix.

You will also notice that the “childish” type of the cell changes, so to speak, and not the cell itself. Rotation of the entire cell will cause the part above and below to be inaccessible for viewing, and we will get strange visual effects, such as vibrations and clipping the cell. ContentView cell contains all the component parts.

Not all properties support animation. Core Animation Programming Guide ( Core Animation Programming Guide ) provides a list ( list of animatable properties ) for clarification.

Compile and run the application. See how data cells incline:
image

Swift Refactoring

The original version of Objective-C provides a one-time definition of the start of a transformation. In the above version of the source code, it is calculated each time by animate () in a new way. How to do it in Swift?

One way is to use immutable storage, which is determined by the transition to the expression. Replace the contents of the TipInCellAnimator.swift file with:

 import UIKit import QuartzCore let TipInCellAnimatorStartTransform:CATransform3D = { let rotationDegrees: CGFloat = -15.0 let rotationRadians: CGFloat = rotationDegrees * (CGFloat(M_PI)/180.0) let offset = CGPointMake(-20, -20) var startTransform = CATransform3DIdentity startTransform = CATransform3DRotate(CATransform3DIdentity, rotationRadians, 0.0, 0.0, 1.0) startTransform = CATransform3DTranslate(startTransform, offset.x, offset.y, 0.0) return startTransform }() class TipInCellAnimator { class func animate(cell:UITableViewCell) { if let view = cell.contentView { view.layer.transform = TipInCellAnimatorStartTransform view.layer.opacity = 0.8 UIView.animateWithDuration(0.4) { view.layer.transform = CATransform3DIdentity view.layer.opacity = 1 } } } } 


Notice the program code that generates the startTransform; now it's like a property of the TipIn CellAnimatorStartTransform class. Instead of defining the property of the creation method and the changes with each query, set the default transformation property by assigning an expression to it and assigning a pair of empty brackets. The brackets allow you to immediately call the expression and assign the return value to the property. This initialization idiom is discussed in Apple's Swift book in the initialization section. For more information, see “Setting the default value property of an expression or function”.

Note: it would be nice to do the TipInCellAnimator property in the TipInCellAnimatStartTransform class, but at the time of this writing, the class properties are not yet implemented in Swift.

Adding constraints to transformations

Although the animation effect is quite concise, use it with caution. If you have ever experienced discomfort when viewing a presentation due to the abuse of sound effects or animation effects, then you have an idea of ​​what glut or abuse is. In your projects, try to have the animation present only when the cell first appears - when it scrolls upwards. When scrolling back up, the cells should be without animation.

It is necessary to develop such a method in order to avoid re-animation of the cells shown earlier. For this, you will see the Swift Dictionary (Dictionary), which provides a quick search by key.

Note: The instruction set is an unordered collection of unique records that do not have duplicates, and an array is an ordered set that allows duplicates. The Swift Library (The Swift Standard Library) does not include a set of instructions, but it can be easily reproduced by Dictionary of Bools.

Penalties for using the Dictionary (Dictionary), therefore, are small, so perhaps the Swift team has removed them from the first release. A common disadvantage of a set of instructions or dictionary keys is that they do not guarantee consistency; however, the ordering of your cells is done by the data generator, so this is not a problem.

Open MainViewController.swift and add the following class property:

 var didAnimateCell:[NSIndexPath: Bool] = [:] 


Here we create an empty dictionary (dictionary) that recognizes NSIndexPath as a key and Bools as properties. Then replace the tableView method (tableView :, willDisplayCell :, forRowAtIndexPath :) with the following:

 override func tableView(tableView: UITableView!, willDisplayCell cell: UITableViewCell!, forRowAtIndexPath indexPath: NSIndexPath!) { if didAnimateCell[indexPath] == nil || didAnimateCell[indexPath]! == false { didAnimateCell[indexPath] = true TipInCellAnimator.animate(cell) } } 


Instead of animating the cell each time it appears when scrolling up or down the table, make sure that the cell's indexPath is stored in the dictionary. If this is not the case, then the cell was shown for the first time, so you should start the animation and add indexPath to your instruction set. If it is already in the set, you should not do anything.

Compile and run your project; swipe up and down the tableview and you will only see the cells that were animated when they first appeared on the screen:

image

What to do next?

In this tutorial, you have added animation to standard visualization control methods. The implementation details of the animation were not recorded in the MainViewController class; on the contrary, they were moved to the auxiliary class. Maintaining class responsibilities in the active state, in particular for display controllers, is one of the main challenges for the development of IOS. You can download the finished project.

Now that you have learned the basics of adding animation to cells, try changing the values ​​of your transformation to see what other effects you can create. Some ideas:

1. Faster or slower animation.
2. Greater tilt angle.
3. Different offsets: if you change the angle of rotation, you will most likely need to change the offset so that the picture looks straight. What will the image look like if you completely lower the offset and use the parameter value (0, 0)?
4. Be creative and create original images.
5. For advanced users: can you get the effect of turning the table on a horizontal or vertical axis? Can you make it seem like a complete coup?
6. For advanced users: add the else (other) clause to the tableView (tableView :, willDisplayCell :, forRowAtIndexPath :) and get different animation effects when the data cells are displayed a second time.
image
Crazy turns that you can apply to data cells.

Even after studying a simple animation guide from this article, you can create an infinite number of variations based on this information. Animation can be a great addition to user actions, such as turning a cell around in a circle, fading out, or appearing when presenting or deleting a cell.

ps Translation does not claim to be the most correct and the best translation in Habré, if you have any comments, write in a personal, I will rule. Thank you for understanding.

Source: https://habr.com/ru/post/234853/


All Articles