Advanced iOS Animations
This post will be probably very long and will cover a lot about making your app as juicy as possible. Best iOS apps have heavily animated UI and guide users by themselves so today we will talk about how to take advantages of all new xCode features, and how design app or how to use eyes in terms of imagining your app being animated.
There are some very basic skills that you need to become iOS dev, good knowing of API is a 80% of your success to become good iOS developer. Old wolfs who were starting from 3.2 know what kind of hell we actually have to pass to get today’s ARC, IB improvements and much more. But there is something that can make you become one of those ninjas who put his “wow” effect to every app they touch. Today I will show you how to convert simple record app to something breathtaking. It will be first part of record app tutorial connected with Core Audio (I will talk about CA next time.) but today we focus only on design, interface builder and last but not least animations of user interface.
There are some things that you actually need to learn if you want to survive in iOS world and most of all become a SWAT team member of iOS developers, those things are:
- Learn GIMP or Photoshop
- If you don’t want to learn photoshop at least you should know how to import colors, fonts etc.
- Buy notepad and some pencils.
- Spend a lot time experimenting with UIAnimations and Gesture Recognizers
- Read documentation! (even those old 4.X API)
- Attend to Hackatons.
- Fail a lot :) without that you cannot learn
- Take criticism (this one is probably most important)
- Learn OpenGL
- And much more ;)
More time you spend on all of this less time you will need to build an iOS app. Look at the video below i build a project for this post in one day and put even to much animations but i want to show you how to make your app feel alive, and tell user he can interact with it. It gives this feeling of “doing something” all the time.
So how i achieve this ? Most of all hard work but there are some key things that will allow you to do the same ;)
Knowing at least one graphic editor will let you save a lot of time and work. Even if you are not a master chief graphic designer with good hand. You can still at least modify or draw your own simple assets. And most important if your UI guy is on vacation and you just need to resize asset, or put some alpha on it you can do it by yourself, common it’s not a rocket science.
More advanced tool and not cheap but most companies have it so you can still sit with graphic and look how he/she do some stuff or ask him/her how to use some basic functions. e.g: most design are done in photoshop so instead of getting UI image and some guides why not to ask to get PSD so you can import all directly from PSD to xCode by e.g: simply cmd+c/v hex colors or font names and sizes? less work for designer, and for me it’s way more elegant and faster to implement.
Long time ago there was an argument if it’s really useful and safe to use IB but today when we have autolayout ? As George Carlin say’s - “It’s bullshit and it’s bad for you” and i cannot agree more. User IB as much as possible!. There are now so many COOL features that may dramatically speed up your development and decrease lines of code. And as we know less code - better to maintain, debug and of course less bugs. Some features that can save a lot of our work:
IB_DESIGNABLE - new feature that allow you to see a preview of your custom control in IB that’s a game changer because it’s allow you to see some of your work without even opening app on device or simulator.
Take a look IB without designable:
And with enabled designable controls preview:
Interface Builder Preview - super cool feature, and one of the most wanted from the time autolayout was introduced. Simply this allow you to see preview of your app layout on ALL selected devices. Again no need to run app and you can see if there are no glitches in your autolayout UI.
Assets catalog - Now when we have new iPhones with @3x resolution assets catalog is only place when you can manage all of assets without getting mad. Also it allow you to FINALLY set rendering mode of asset! no more:
Also allow you to manage
Size Classes And here how it looks:
Those are one of most used things that will save your day many times. There is of course a lot more but it’s time to get to our main topic which is:
Without them your app will be at least average if you really want to make your app look epic put as much animations as you can, your app need to live otherwise it will die in all those apps that spam appstore day by day
But before we start, you need to learn how to “see” animations in your app. I’m always doing sketches so I can visualize how may app will behave like this one:
If you are lucky and you have designer he can always do it for you or even make some animation using AfterEffects and export to gif or some video. It’s always a good thing to have something like this so you will not lose the “idea” of animation. Ok enough of talking time for some code!
First let’s talk how I did this idle spinner animation when app is not used. I saw this kind of loading spinner in some games and I decided to do the same here so app give that feeling of “doing something” while not used. So first I put some multiple
UIView in my container as the each one of them will be animated using simple rotation of it’s center
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
This will give us nicely done arcs in our IB of course we are declaring our view as:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
So we can see live preview in Interface builder, see
IBInspectable ? this allow you to declare variables available from interface builder so you can modify it look without compiling.
Ok so how to animate the views ? there are actually two ways of doing that one by using
UIView animateWithDuration or
CABasicAnimation from Core Animation. I want to focus today mostly on Core Animation so i will show some simple UIView animations later on, but for now a bit about Core Animation. It’s one of the low level frameworks provided by Apple allowing to create animations that can be apply directly on views layers, notice that we are not working on UIView anymore we are going deeper by playing with UIView layer property.
CALayer is a lightweight entity used to acutally do drawing for you under the hood. Layer can have sublayers so it’s pretty similar to working with views. The main difference is that you can do some animated drawing which can’t be achieved by using UIView
drawRect: method. You can even create your own fully custom layers. Of course there is some magic going under the hood for you. If you read documentation you will notice there is something called presentationLayer this guy hold current view state while animating and this may be useful in some cases. This is also a good moment to tell why iOS works so damn fast, and why doing this kind of animations on Android make some of developers working on it commit suicide; the answer is simple:
iOS perform hardware accelerated animations - what does this mean? iOS rendering pipeline is based on OpenGL and its directly connected to whole API (right now they probably doing some Metal SDK transitions to speed up even more some stuff) That’s why every thing animated in iOS works so smooth.
Ok time to explain how do we actually animate idle arcs:
1 2 3 4 5 6 7
Creating rotation animation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Applying animation to particular view layer:
1 2 3 4 5 6 7 8 9 10 11 12 13
Ok now because we set us as delegate to animation we have to handle it in this function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
For example you can also use regular UIView animation that’s how I manage to do this magic echo impulse ring that blinks all the time:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
Doing heartbeat animation is also very simple again we will use
CABasicAnimation and the
autoreverses property of animation. This will simply reverse animation to its original state automatically.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
When it comes to simple animations that gives wow effect, the one of the most important places in your app is it’s menu. If you build cool and fancy menu users will way more gladly use it even without doing anything just to play with it.
My menu uses new iOS7 feature: animation with spring to be more precise:
1 2 3 4 5 6 7
This animations apply spring effect to your animation which in many cases looks super fancy and cool and you can combine this with any other animation it’s just something you get for free so why not to use it? the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
Ok we are done with those easy ones now time for some tricky animations. We left two of them, the hole animation that make record button empty inside and arc animation that represent record time animation. (e.g: we get user desired time of recording and he need to fit this time before it run out.)
CALayer contains mask property which tells him what could be actually visible. So simply whatever shape you will apply on your layer using this mask will become transparent. In our case we actually need the opposite we want to tell our view what we want to keep not what we want to cut.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
And because it is also a regular
CALayer you can apply animation to it.
1 2 3 4 5 6 7 8
One more thing, remember that animation apply changes to layer only while animating! if you for example set your layer scale to 0.5 and animate from 0.5 to 1.0 it will go back to 0.5 after animation so your layer need to set proper final value before animating. It’s super important so keep this in mind.
My Pie Chart animation inside drilled button is done using custom build
CALayer i had to do it because regular
CALayer do not allow to animate Bezier path simply, it will interpolate value instead of redrawing it properly. You can find some detailed info about how it is done on Pixel-in-Gene Blog but the basic idea is to subclass
CALayer and overwrite
-(void)drawInContext:(CGContextRef)ctx which is called every time property changes. Here is detailed custom pie chart implementation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
As you can see it’s similar to regular
drawRect: call but in
CALayer we need to tell it actually when to redraw. We do this by overwriting
+ (BOOL)needsDisplayForKey:(NSString *)key; method in our custom class. This will tell the layer to redraw every time our color or angle changes even when animated.
Another thing that is done here is automatic animation generation for every property we have. To do this simply overwrite
- (id and compare the event key with our property by using
[event isEqualToString:NSStringFromSelector(@selector(propertyToCompare))] and fire up animation if we detect property that we want to animate.
One more thing… see the
@dynamic keyword on properties instead of automatically generated
@synthesize we do this because CoreAnimation will create sub values and dynamically update original one while animating the property. Basically if you used CoreData you should be familiar with it, if not the simplest explanation to
@dynamic is that by using it we tell compiler that our setter and getter will be generated outside the class and can be dynamically created instead of static compile time code generation in class.
And that’s all for today, as always source code available on my github. Next time i will use this code to finish this app using
Core Audio as another blog topic.