Today we'll continue looking at UICollectionView's more advanced capabilities by checking out a little-known feature hiding inside UICollectionViewController.
It allows us to automatically animate the transition between layouts when pushing on to a navigation controller stack. Neat!
Let's give it a try.
We'll start with the same simple baseline collection view controller we used in Bite #306, and Bite #307, SquaresViewController.
That's it. UIKit will notice that we've set our BigViewController's useLayoutToLayoutNavigationTransitions to true, and will automatically animate the transition between the two layouts.
Note that the automatic transition animation that UIKit renders is smart enough to make sure the selected cell is still visible after we push in. A nice touch.
First, the same UICollectionView is actually reused when all of this magic happens. The pushed on view controller will not create its own. This may or may not matter for any given app, but good to know.
Second, the root view controller (SmallViewController in our case) will still be set as the delegate and dataSource when the new view controller is pushed on.
If we needed to change this behavior, we could conform to the UINavigationControllerDelegate protocol and change these values each time a different view controller is about to be be shown. The code might look something like this:
Now we can toggle back and forth between our two layouts with a nice looking animation. Very cool.
It's super handy how the setCollectionViewLayoutfunction is smart enough to alter the animtion so the cell we selected is still in view once the animation completes.
We can see this effect exaggerated when we bump up the itemSize of our "big"layout:
One final note here: This just one approach. There are tons of different ways to achieve this (and similar) behavior. We'll take a look at more as we dive deeper into collection views in upcoming Bites.
Have a specific UICollectionView question you'd like answered? Send it along!.
UICollectionView has always been a powerhouse. Its variety and versatility are tough to understate.
We've covered it a bit here on LBOC, but we've still only just scratched the surface. Today we'll begin to dive deeper in what all it can do by customizing how new collection view cells animate when they're being inserted. Let's begin!
We'll start by creating a new single viewapp in Xcode.
We'll drag out a UICollectionViewController in Interface Builder, set its class to be the ViewController one that comes with the Xcode template, then update ViewController.swift to have some basics:
With this, we have a nice mostly-"boilerplate" setup. Just some square, randomly-colored, cells that fade in when they're inserted:
Not bad. Now let's customize the behavior of those cells as they're being inserted. For this, we'll need our own custom UICollectionViewLayout subclass.
Specifically we'll subclass UICollectionViewFlowLayout and override a few functions to customize the behavior of inserted cells.
What we've done here is to grab the layout attributes our collection view was going to use for the newly inserted item, and modify them slightly, before passing them along back to the system.
Here we've added a transform to scale the item down when it is first added, this will give us a nice "zoom up" effect as each item is added:
That looks neat, but let's try for something even funkier. We can change our transform line to:
Animation plays a key role in how we understand the user interfaces in the software we use. This role expands itself when animations are driven directly from a user's gestures or interactions with the interface. Today we'll look at a new framework that can help us create these types of experiences without breaking a sweat. Let's dive in.
As the project's README puts it: "all animation is the interpolation of values over time."
Interpolate helps us describe the relationships that we want to exist between a user's gesture and the interpolated values that should result for the properties of our views. Let's try it by animating a color.
Since Pan GRs report every step of their progress as a simple float (from 0.0 - 1.0), we can simply set that progress percentage value directly on the Interpolate object.
There's tons more too, Interpolate supports easing functions, and works on all sorts of foundation types (points, rects, colors, etc.).
Creating good-looking animations can be a lot of work. We could spend our whole day learning about curves and scaling, and transforms, and oh boy...
Instead, what if we could simply apply some popular animations to our UI elements with almost no effort at all? Today we'll check out a library called Spring that allows us to do just that.
Spring supplies a ton of common animations like shake, pop, squeeze, wobble, etc.
If we're using Interface Builder, we actually don't even need any code at all. We just use one of Spring'sUIView-subclasses, then we supply our animation by name.
In code, it's equally simple:
layer.animation="shake"layer.animate()
These all work great out of the box, but we can still customize the curve or individual properties if needed. Neat!
More info about Spring can be found at git.io/spring
Most iOS developers have used the fantastic UIViewanimateWithDuration family of functions. But there's another, slightly-lesser known static function on UIView that can help us transition like a pro. Let's check it out:
The function we'll be trying is transitionWithView. At first glance you'll see it's takes the same duration, options, and closures as its more-popular sister function.
However, instead of applying our changes over time, this function will (conceptually) take a snapshot of our view before and after the work in the animations** closure** is performed, then visually transition from the first snapshot to the second.
The type of transition depends on the animation option we pass in. We can do everything from simple cross-dissolves (fades), to fancy 3D flips. Super handy for simple transitions.
Download a sample project at j.mp/bite193. In it, we flip a thumbs up emoji using this incredibly simple technique.
Animation is one of the greatest parts about building (and using) iOS apps. The APIs however, can feel a bit scattered. UIView's animation functions are wonderful, but some animations require using Core Animation directly.
When they do, things get progressively more complex depending on if we need to run multiple animations in succession, or just run code after an animation completes.
Today we'll look at a great library from Marin Todorov called EasyAnimation that improves on all of this. Let's dive in:
EasyAnimation makes animating CALayers that normally would require CABasicAnimation (or one of its siblings) work with the standard UIView.animateWithDurationfunctions:
Under the hood, EasyAnimation does all the heavy lifting of translating our animations back into CAAnimation code and handling all of the implementation details for us. Neat!
Normally, if we wanted to run code after one the animations on a CALayer finished, we'd need to wire up an animation delegate, implement the callback functions, make sure to clean up after ourselves, etc.
With EasyAnimation though, we're able to just use the normal completion closure.
Last but certainly not least, EasyAnimation makes "chaining" multiple animations together (running one after another) extremely convenient. It also supports cancelling the chain, repeating, delays and more:
iOS's software keyboard has evolved quite a bit over the years. Just last week we saw a new variant of it on the new iPad Pro. The user can also connect a hardware keyboard at anytime, hiding the software one. It's important, now more than ever, that we not make any assumptions about how and when the keyboard will transition on and off the screen.
It'd be great if the system could tell us all the details of how and where it's about to animate. Then we could use that info to move our own controls and views right alongside it. For this we can listen for some keyboard notifications_, and react appropriately. Let's take a look.
We'll start by registering for two notifications in viewDidLoad:
Next, we'll grab all the necessary values out of the notification'suserInfo, and use them to animate our own views exactly alongside the keyboard as it slides on or off the screen:
We grab the start and end frames, convert them to our view controller's view's coordinate space, and use the difference to move a constraint. Then we animate the constraint like we covered Bite #9.
Animating between two sets of Auto Layout constraints is quite simple.
All you have to do is update your installed/configured constraints and then call layoutIfNeeded inside of a UIView.animateWith* closure.
classDoorsViewController:UIViewController{varopen:Bool=false{didSet{transition()}}functransition(){self.view.layoutIfNeeded()// force layout before animatingUIView.animateWithDuration(0.4){// change constraints inside animation blockself.updateConstraintsForDoors()// force layout inside animation blockself.view.layoutIfNeeded()}}funcupdateConstraintsForDoors(){leftDoorHorizontalConstraint.constant=open?-16:-leftDoorView.bounds.size.widthrightDoorHorizontalConstraint.constant=open?-16:-rightDoorView.bounds.size.width}}