📜 ⬆️ ⬇️

Animations in iOS for beginners. Models, classes from Core Animation, blocks

I think all developers would like to decorate their applications to one degree or another with various effects. The Android department of Live Typing has already released two articles on this topic: about the type of Animator classes and its own CannyViewAnimation library , which replaces the imperfect ViewAnimator. I represent the iOS development department of our company and I also want to speak on a topic that is more important than it seems.

This article is an introduction to the world of animations for iOS applications. It is recommended to those who never worked with animations, or do not understand some points in standard iOS animations.

Both iOS developers and designers agree that animation is one of the key elements of user interfaces. She needs to:


In other words, animation is a way to give dynamics to a specific element within an interface, or to an interface as a whole.
')

Basic concepts


In our conversation about animations, we cannot do without a few fundamental things. We define them:

Core Animation is a framework for working with basic animation classes: CABasicAnimation, CAKeyFrameAnimation, CATransition, CAAnimationGroup. Using Core Animation is fully automated: no need to create loops and timers to make the animation.

CALayer - a set of classes that control the animation of the root layer of an object. Classes access the layer and apply one of the properties to it. Among these properties are the size and position of the layer, the background color of the layer, the shadow, rounded corners, and the like.

When you create an animation, specify the path to the CALayer properties, use the animationWithKeyPath method or the keyPath property. The latter are assigned by the string view @ "name_key". Here are some examples:

CALayer * layer = [CALayer layer] .opacity
CALayer * layer = [CALayer layer] .position
CALayer * layer = [CALayer layer] .shadowRadius

With the use of animationWithKeyPath we will get to know better in the section "Examples of explicit animations". And all the properties can be found here .

Animation models


There are two animation models: implicit and explicit.

Implicit animation


The implicit animation model Core Animation assumes that all changes in the layer properties being animated should be gradual and asynchronous. Animation will occur without effects, moving from one value to another.

Suppose that the current position of the layer in (theLayer.position.x, theLayer.position.y)

Objective-c:

theLayer.position=CGPointMake(100.0,100.0); 

Swift:

 theLayer.position = CGPoint(x: 100.0, y: 100.0) 


Explicit animation


An explicit animation model requires creating an animation object and setting initial and final values ​​and will flow smoothly from one value to another. The animation will not start until it is added to the layer.

A set of animation classes inherited from Core Animation:

CABasicAnimation. Provides a simple interpolation between values ​​for a layer. For example, with this class we can move a layer from one point to another, change the value of transparency from one to another, etc. Using the class, you can make animations to draw the user's attention to a specific object on the screen or show the training information in the form of animation.

Objective-c:

 CABasicAnimation *theAnimation; theAnimation=[CABasicAnimation animationWithKeyPath:@"position"]; theAnimation.duration = 3.0; theAnimation.repeatCount = 2; theAnimation.autoreverses = NO (YES); theAnimation.fromValue= [NSValue valueWithCGPoint:CGPointMake(screenWidth/2, _animationButton.frame.origin.y)]; theAnimation.toValue= [NSValue valueWithCGPoint:CGPointMake(100, 100)]; [theLayer addAnimation:theAnimation forKey:@"animatePosition"]; 

Swift:

 let theAnimation = CABasicAnimation(keyPath: "position"); theAnimation.fromValue = [NSValue(CGPoint: CGPointMake(screenWidth/2, self.animationButton.frame.origin.y))] theAnimation.toValue = [NSValue(cgPoint: CGPoint(x: 100.0, y: 100.0))] theAnimation.duration = 3.0; theAnimation.autoreverses = false //true -      ,   theAnimation.repeatCount = 2 theLayer.addAnimation(theAnimation, forKey: "animatePosition"); 

In the upper animation, the parameter autoreverses = YES, in the lower - NO. That is, the position either does not return to its original value, or returns smoothly.


CAKeyframeAnimation. Provides a change in the values ​​of the layer property by the values ​​that are specified in the array. For initialization, the animationWithKeyPath method is used with an indication of the property that needs to be changed. We also specify an array of values ​​that will be presented at each stage of the animation. We can set several values ​​to which the layer will move - it turns out to be much more interesting than simply changing the position from one point to another, as it was in the examples above.

Objective-c:

 NSArray * pathArray = @[ [NSValue valueWithCGPoint:CGPointMake(10., 10.)], [NSValue valueWithCGPoint:CGPointMake(100., 10.)], [NSValue valueWithCGPoint:CGPointMake(10., 100.)], [NSValue valueWithCGPoint:CGPointMake(10., 10.)], ]; CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; pathAnimation.values = pathArray; pathAnimation.duration = 5.0; [self.label.layer addAnimation:pathAnimation forKey:@"position"]; 

Swift:

 let animation = CAKeyframeAnimation() let pathArray = [[NSValue(cgPoint: CGPoint(x: 10.0, y: 10.0))], [NSValue(cgPoint: CGPoint(x: 100.0, y: 100.0))], [NSValue(cgPoint: CGPoint(x: 10.0, y: 100.0))], [NSValue(cgPoint: CGPoint(x: 10.0, y: 10.0))], ] animation.keyPath = "position" animation.values = pathArray animation.duration = 5.0 self.label.layer.add(animation, forKey: "position") 


CATransition . Provides a transition effect that affects the content of the entire layer. It disappears, pushes or reveals the contents of the layer during animation. CATransition can be used to navigate between a UIView or to change transitions between a UIViewController: smooth appearance, appearing from different sides, appearing on top of current content, pushing out current content.

In order to implement a custom transition between screens, you need in the pushViewController: animated method: specify NO (false) for the parameter animated.

Objective-c:

 CATransition *transition = [CATransition animation]; transition.duration = 2.35 transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; transition.type = kCATransitionFade; [self.navigationController.view.layer addAnimation:transition forKey:kCATransition]; [[self navigationController] pushViewController:[NewViewController new] animated:NO]; 

Swift:

 let transition = CATransition() transition.duration = 2.35 transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) transition.type = kCATransitionFade self.navigationController?.view.layer.add(transition, forKey: nil) self.navigationController?.pushViewController(ViewController(), animated: false) 


Types for transition.type:


Subtypes for transition.subtype:


The entire list of types and subtypes of CATransition can be viewed in the Apple official documentation for developers.

Types:
Swift
Objective-c

Subtypes:
Swift
Objective-c

CAAnimationGroup . Allows you to create an array of animated objects that are grouped together and will work simultaneously.

Objective-c:

 CABasicAnimation *positionAnimation = [CABasicAnimation animationWithKeyPath:@"position"]; [posAnimation setFromValue:[NSValue valueWithCGPoint:CGPointMake(_animationButton.frame.origin.x, _animationButton.frame.origin.y)]]; [posAnimation setToValue:[NSValue valueWithCGPoint:CGPointMake(100, 100)]]; posAnimation.autoreverses = YES; // ,       ,     . [posAnimation setDuration:10.0]; [posAnimation setBeginTime:0.0]; CABasicAnimation *heightAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size"]; heightAnimation.autoreverses = YES; [heightAnimation setFromValue: [NSValue valueWithCGSize:CGSizeMake(_animationButton.frame.size.width,_animationButton.frame.size.height)]]; [heightAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(_animationButton.frame.size.width, 200)]]; [heightAnimation setDuration:10.0]; [heightAnimation setBeginTime:5.0]; CAAnimationGroup *group = [CAAnimationGroup animation]; [group setDuration:10.0]; [group setAnimations:[NSArray arrayWithObjects:posAnimation, heightAnimation, nil]]; [_animationButton.layer addAnimation:group forKey:nil]; 

Swift:

 var animations = [CABasicAnimation]() var posAnimation = CABasicAnimation(keyPath: "position") posAnimation.duration = 1.0 posAnimation.autoreverses = true posAnimation.fromValue = [NSValue(cgPoint: CGPoint(x: self.animationButton.frame.origin.x, y: self.animationButton.frame.origin.y))] posAnimation.toValue = [NSValue(cgPoint: CGPoint(x: 100.0, y: 100.0))] animations.append(posAnimation) var heightAnimation = CABasicAnimation(keyPath: "bounds.size") heightAnimation.autoreverses = true heightAnimation.duration = 10.0 heightAnimation.fromValue = [NSValue(cgSize: CGSize(width: self.animationButton.frame.size.width, height: self.animationButton.frame.size.height))] heightAnimation.toValue = [NSValue(cgSize: CGSize(width: self.animationButton.frame.size.width, height: 200.0))] heightAnimation.beginTime = 5.0 animations.append(heightAnimation) let group = CAAnimationGroup() group.duration = 10.0 group.animations = animations self.animationButton.layer.addAnimation(group, forKey: nil) 

Here the BeginTime parameter specifies the interval after the start of the animation.

The animation of the change in position begins immediately after the start, and the animation of the change in the height of the button starts from the fifth second.


Removing animations


We can remove both the specific animation from the layer and all the animations.

Delete a specific animation.


When creating the animation, we specified the key @ "animateOpacity", by which we can access it. To remove this animation, do the following:

Objective-c: removeAnimationForKey: @ "animateOpacity"

Swift: removeAnimationForKey ("animateOpacity")

Remove all animations.


To remove all animations from a layer, you need to send a message to removeAllAnimations:

Objective-c: [theLayer removeAllAnimations];

Swift: theLayer.removeAllAnimations ()

Animation blocks


There are pre-prepared blocks in which you can play the desired animation (change in transparency, position, size). There are two such blocks: animations and completion. We define their purpose:


Animation blocks should be used when changing one value of a layer (object) to another with the subsequent saving of a new value. In the blocks, we can change both the layer properties and the properties of the object itself.

Example 1. The alpha buttons change from the current state to the final state, which is indicated in the block, in 3 seconds.

Objective-c:

 [UIView animateWithDuration:3.0 animations:^{ _theButton.alpha = 0.0; }]; 


Swift:

 UIView.animateWithDuration(3.0, animations: { self.theButton.alpha = 0.0 }) 



Example 2. Change the position and height of the button

Objective-c:

  CGRect frame = _animationButton.frame; frame.origin.y = 100; frame.size.height = 200; [UIView animateWithDuration:1.5 delay:0.0 options: UIViewAnimationOptionCurveEaseOut animations:^{ _animationButton.frame = frame; } completion:^(BOOL finished){ NSLog(@"Done!"); }]; 


Swift:

 var frame = self.animationButton.frame frame.origin.y = 100 frame.size.height = 200 UIView.animate(withDuration: 1.5, delay: 0.0, options: .curveEaseOut, animations: { self.animationButton.frame = frame }) { (true) in print("Done") } 


Here the first parameter is the speed with which the animation will play;
the second parameter is the delay;
the third parameter is options, that is, in what form the animation will play.

Animation playing options:

UIViewAnimationCurveLinear - animation runs at a constant speed for a specified time;
UIViewAnimationCurveEaseOut - the animation starts quickly and slows down towards the end;
UIViewAnimationCurveEaseIn - the animation starts slowly and accelerates towards the end;
UIViewAnimationCurveEaseInOut - the animation starts slowly, accelerates and slows down again.

There are animation blocks in which animated transitions take place between a UIView or the addition of elements to a UIView, as in the example below. They use the transitionWithView block, which is necessary for an animated transition or a UIView view or objects inherited from UIView.

Objective-c:

 [UIView transitionWithView:self.view duration:1.5 options:UIViewAnimationOptionTransitionFlipFromBottom animations:^ { [self.view addSubview:self.imageView]; } completion:^(BOOL finished){ if (finished) { // Successful } NSLog(@"Animations completed."); // do something… }]; 


Swift:

 UIView.transition(with: self.view, duration: 1.5, options: .transitionFlipFromBottom, animations: { self.view.addSubview(self.imageView) }, completion: nil) 

This is what happens in this case: In this example, we add a picture on the UIView with animation:


The UIImageView object displays a single image or sequence of images in an animated interface. We can animate UIImageView without using blocks and animations like CABasicAnimation. UIImageView has animationImages, animationDuration, animationRepeatCount properties, which means that we can, by transferring to animationImages an array with pictures that we need to play, start the UIImageView animation.

Objective-c:

 _chicken = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"chicken_normal_fly_1.png"]]; [_chicken setCenter:CGPointMake(150.f, 400.f)]; NSMutableArray *flyAnimFrames = [NSMutableArray array]; for(int i = 1; i <= 8; ++i) { [flyAnimFrames addObject:[UIImage imageNamed:[NSString stringWithFormat:@"chicken_normal_fly_%d.png", i]]]; } _chicken.animationImages = flyAnimFrames; _chicken.animationDuration = 0.25f; [_chicken startAnimating]; 

Swift:

 var imgListArray :NSMutableArray = [] for countValue in 1...8 { var strImageName : String = "chicken_normal_fly_\(countValue).png" var image = UIImage(named:strImageName) imgListArray.add(image as Any) } self.imageView.animationImages = imgListArray; self.imageView.animationDuration = 0.25 self.imageView.startAnimating() 



Conclusion


In this article, I gave a minimal level of knowledge about iOS-animation, with which your application will become more colorful and more reliably capture the attention of an iPhone or iPad user. Now our team is working on a project with more complex animations in which timing function and delay play a significant role. We will translate the experience gained into the article, so stay in touch and thank you for your attention. I hope the material was useful.

If you have any questions, wishes or comments - welcome to the comments.

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


All Articles