Dynamic interfaces create fluid and rich interactions. Hear about new dynamic behaviors that have been added in UIKit and how to take advantage of them in your applications. Gain a practical understanding of how to integrate dynamics with AutoLayout. Learn about enhancements to UI Kit Visual Effects.
MICHAEL TURNER: Welcome to the final day of WWDC,
and 'What's New in UIKit Dynamics and Visual Effects.'
My name is Michael Turner,
joined by my colleague David Duncan.
We are both on the UIKit team here at Apple.
So before we get started today,
I just want to recommend some great sessions.
Since this is an introductory talk,
we have some great sessions
from years past covering UIKit Dynamics and visual effects.
So today we are going to start with a brief overview
of the dynamic animation system, and we'll do
that with a basic example, and then we are going to dive right
into what's new this year with UIKit Dynamics.
Then David's going to come up and talk to us
about visual effects, and how you can utilize those
in your application.
And finally, we are going to talk a little bit
about best practices using UIKit Dynamics
and auto layout in your application.
So when we talk about UIKit Dynamics we are talking
about a 2D, physics-inspired animation interaction system.
This has a very composable and declarative API
for exposing high level animations in your app.
We are not talking about replacement for Core Animation
or UIView animations, rather another tool
to help you create great custom effects in your app.
So let's look at an example.
So here we have a basic sliding view
and the user can pan the view, but if you let go it falls back
down as if under the influence of gravity.
Now, it doesn't fall through the bottom of the phone.
Rather, it stops on the bottom edge, bounces a bit,
and then comes to rest.
So let's look at how we can create this basic example.
First you need to start
by determining a great reference view.
Here, we've chosen the view controller's view
that contains our sliding view.
And once we have a reference view, we then need
to create a dynamic animator and associate that reference view.
The dynamic animator will hold the overall context
for our animations, and its main job is to keep track
of behaviors and dynamic items.
So for our sliding example, we have a sliding behavior.
And one of the great things about UI dynamic behavior,
is that higher-level behaviors can be composed
of more primitive ones.
So our sliding behavior is nothing more than a composition
of gravity, collision, and attachment.
And later on, we will show you how we used UIAttachmentBehavior
and the new things we've added there to make this even simpler
than it would have been in the past.
So once we have our sliding behavior,
we now need a dynamic item.
Here we've chosen the sliding view, just a UIView
which automatically conforms to the dynamic item protocol,
so it's a great option.
So we take our dynamic item, associate it
with the sliding behavior,
and the sliding behavior to the animator.
Now the animator will automatically determine
when the system is at rest or in motion, so this is all you need
to create this great effect.
So now we have seen a basic example.
This is what's new this year in UIKit dynamics.
We have support
for non-rectangular collision bounds on UIDynamicItem.
We have a brand new UIDynamicItemGroup
that allows multiple items to behave like one item
in the engine, and we have a brand new behavior
that models vector force fields.
We have some basic enhancements to UIDynamicItemBehavior,
as well as UISnapBehavior, and we'll see some great additions
to UIAttachmentBehavior, and we will finish
up with some new ways that you can use
to debug your dynamic animations.
So, in iOS 9, we added UIDynamicItem
CollisionBoundsType which offers you three new ways
to specify the collision bounds for your dynamic item.
And by default your collision bounds will be rectangular
matching what's returned from the bounds accesser
on the dynamic item protocol.
And now you can specify an ellipse type, which will derive
from the bounds width and bounds height on the protocol.
And finally, you can specify a UI BezierPath to use
for the collision bounds of your dynamic item.
Now, to accomplish this, we have taken the existing dynamic item
protocol and we have extended it with two optional properties.
And if you don't implement either
of these optional properties you will receive rectangular
collision bounds, as you have in the past.
If you implement the first collision bounding type
and return ellipse, will derive one,
an ellipse from the bounds width, bounds height.
If you implement the first and return a path,
we will then call you back for the second
at which point you will need to provide a UI BezierPath to use
for the collision bounds.
So if we were to model a collision between items
with different collision bounds, and let's add a few more here
for good measure, it might look something like this,
where this collision looks a lot more realistic
than it would have in the past,
had all the items had rectangular collision bounds.
Now, there are a few restrictions when using a path
for collision bounds and in particular,
the BezierPath must be convex, counter-clockwise wound,
And these are pretty basic if you think about it,
nothing too fancy there.
We also need to keep in mind that the point 00
in the BezierPath will represent the dynamic item's center point
when the item is on screen.
So that's what's new in collision bounds.
Let's talk about dynamic item groups.
And this is a basic way to take multiple items
and make them behave as one item in the underlying engine.
And the group preserves respective positions
and each individual collision bounds for each item.
So for this reason, you should associate items with a group
and not with behaviors individually.
Instead associate them with the group and the group
with any behaviors you would
like to associate with the animator.
And this will impose those behaviors
on the items as a whole.
And a group cannot be added to other groups.
This is a one-level abstraction.
So this can be a great way to create concave
or other complex geometry not capable
with the dynamic item bounds path, and also have
that influenceable by behaviors as a whole.
So, let's return to that sliding example for a moment.
So instead of just panning and having it to fall back down,
let's say we want it to bounce slightly when the user taps,
maybe to indicate that we can pan.
And to do this, we just need
to add a brief force to the sliding view.
So let's take a look at that force.
So we can model the force as a vector at the item's center
where the length of the vector corresponds to the magnitude
of the force and the vector points up to indicate
that the direction of the force, in this case we are trying
to move the view up, so it points up.
And to apply the force, we're going to use UIPushBehavior --
where UIPushBehavior, if you recall, has two distinct modes.
It has a continuous mode that represents a constant force
over time, and an instantaneous mode
which represents a brief force at an instant in time,
otherwise known as an impulse.
So for this interaction, we just want a brief force so it bounces
and comes back to rest, so we're going
to use the instantaneous mode.
So we do that; we get a brief force.
But what is causing the view to come back down?
We are putting a force on it that causes it to move up
but it's falling back down.
This is our composite behavior that was composed of a gravity,
a collision, and attachment.
And so gravity is causing it to move back down
and then it bounces with the collision behavior.
But let's look at a little bit more at gravity
and how that's affecting our item.
So we look at the vertical motion over time
of the sliding view, starting with the instant
that we apply the impulse force.
You will notice that the force is applied at one point
and then the item kind of moves up and then arcs back down.
This is because gravity is affecting it at all positions
and all times in our diagram here.
If we add those forces in from gravity, it might look something
like this, where the force is applied
at all positions and all times.
So this is tricky to model.
Maybe we could try and use UI push behavior,
but it would be pretty complex, pretty quickly.
So we really need to think of gravity as more of a field.
And a field's quite simple, it's just a function
that assigns a vector to each point within a given domain,
where our domain, in this example,
is the entire reference view.
So we want gravity to affect our sliding view
in the entire reference view.
So we have taken this idea of a field and we have extended it.
In iOS 9, we are introducing UIFieldBehavior.
And UIFieldBehavior is a way that can be added to a region
of your reference view, and the field is evaluated at each point
within the reference view,
and any resulting forces are automatically applied
by the dynamic animator to the items
that have been associated with the field.
And if you are wondering,
our existing UIGravityBehavior has been implemented
as a field all along, and it's important to keep in mind
that this is simplified physics.
It's been well tuned for performance.
I wouldn't use it for building interstellar space stations
or anything like that.
So let's look at the built-in field types that we offer.
We've got a rich variety here.
We have linear and radial gravity, velocity
and drag fields, a vortex field, we have got a great spring field
that models Hooke's law, we've got electric
and magnetic field types.
And if these all don't quite meet your needs,
we also offer a custom force evaluator,
and we'll see this in a moment.
But let's start with linear gravity here first.
So the first thing you will notice is it exists in a region,
in a domain as we previously said, and it has a strength,
we've used the default strength of one here,
but it's also a directional force,
and then we have used the familiar direction
of gravity here, down, to show this example,
but this can be directed anywhere, really.
So let's look at how radial gravity differs
from that of linear gravity.
And along with existing in a domain and having a strength,
this has a position which can be modeled
with radial gravity as a point mass.
And if you recall, the gravitational force
between two masses is inversely proportional
to the distance squared between the two masses.
So, here, that distance squared between the masses,
that exponent, this is the fall off value of the field.
So as you get farther away from the position of the field,
the force due to the field, it gets -- decreases.
And we also have a minimum radius property here,
and this is just a way to specify how far
from the position point an item must be in order
to feel a resulting force due to this field.
So we also have a noise field,
and the first thing you will notice about a noise field is,
it's time varying, and you can adjust this using the animation
speed with a default value of one,
and zero would indicate a static field.
You can also adjust the level of noise
in the field using the smoothness property.
So let's look at a custom field evaluator.
And this is really quite easy to use.
You create a UIFieldBehavior and initialize it
with a field evaluation block.
We will then call your block
with several field samples containing the position,
velocity, mass, and charge, and time associated
with that field sample and then you can use
that to determine any resulting forces.
Here all we did was take the position, the x position,
and map it to a sin wave.
Pretty cool result.
So these are the -- some of the basic built-in fields
and a basic overview of UIFieldBehavior.
I would like to invite up David to give you a quick example
of showing an inaction.
DAVID DUNCAN: Hello, everybody, and we are going
to take you through an example of something
that I'm certain you have all seen before.
As I'm sure you have all used FaceTime at some point
or another, and so we just have an example
of building a very similar UI
for managing your face in the screen.
As you have been able to see as I have gone through here,
the square moves very nicely as I move it around the screen,
and if I pull it a little away from the corner it bounces back.
If I pull farther, it has
that nice ease-in curve as we are going.
And if I throw it down, it kind
of bounces off very playfully all around the edges.
And you will note when I threw it down, it didn't just kind
of go straight to where it was supposed to go,
it actually had a little physics, it bounced off the side
of the screen and came back into position.
Now, I can do a little thing and trigger a debugging view
of what those forces fields look like.
In this case you can see that we --
In case, you can see that we have four spring fields running
around here, and we have got an easy way to explain what's going
on so if we put this right on the edge,
we know it is going to bounce back.
And if we kind of straddle two, then depending
on where we straddle it will pick one side or the other.
And go through the middle,
and it just picks whichever is closest.
So let's see how we set this up,
and how we can actually set this all ourselves.
So the first thing that we have is this StickyCorners behavior,
and as Mike mentioned, it's built up of other behaviors
to form this complex behavior that does everything we want.
In this case, it has got a collision behavior,
because we wouldn't want your face
to rocket off the side of the screen.
And we have a dynamic item behavior,
that affects the properties of that face.
In this case, we reduce its density
to it's really light feeling in the engine,
but we increase its resistance to motion so that
when it finds a place to settle it doesn't keep spinning
around in that location.
And finally we disable rotation,
because that wouldn't make any sense.
You don't want your face spinning
around as it's going around the screen.
Finally, we have these field behaviors,
the four spring fields that map out the four corners,
and we add those to the behavior too.
Now whenever somebody adds this StickyCorners behavior,
they get all of this behavior for free.
Next, over here in the view controller,
we go to all the usual stuff where we set
up our view hierarchy, but then we also add a pan gesture
recognizer so that the user can pick up the face
and move it around the screen.
This long press gesture recognizer we have here lets me
actually toggle on and off the debug interface.
We create our dynamic animator
and add the StickyCorners behavior to it.
So how does that gesture recognizer work?
Well, as usual, the gesture recognizer goes between states.
It starts at begin, and when we begin, we do some bookkeeping
so that we can keep track of the item,
but we also disable the sticky behavior.
And I will show you how we do that in a second.
Similarly, when it's changed we just move the item around.
And when it cancels or ends,
this is where we do something really special.
We check the velocity that the pan gesture recognizer had
when the user stopped interacting with it,
and we use that to add velocity back
into our dynamic item system.
And this is so that when the user throws that view around,
it continues moving with the force of the user's action,
rather than just suddenly stopping and being taken
over entirely by the field.
And the whole reason why we disabled
and enabled it is for the same reason.
We don't want the fields
to be active while the user is moving it around,
otherwise it is going to slip
out from underneath their finger.
So we can go back over here briefly
and see how the enabled works,
and as you can see, it's really simple.
When it's enabled, we add all of the items back
into the behaviors, and when it's disabled, we take them out.
It's really that easy to create a system like this,
and you can have your own FaceTime-like behavior
in your applications.
And so to show you how to put that debug UI
into your own applications,
I am going to bring Mike back up on stage.
MICHAEL TURNER: Thanks, David.
So it's really, really quite cool, in David's example,
to visualize those field lines,
to understand what was actually going on.
This is pretty mysterious until he turned that on.
So those lines were basically an overlay that shows the field
in your animators' reference view.
And specifically, this overlay can help you visualize fields,
collision bounds, attachments, and whether
or not a particular item is in motion or at rest.
Now, you might be wondering, it's not going to be API.
But it will be accessible in LLDB, and we are advertising it
as an available debug feature on UIDynamicAnimator.
And it's really simple to use.
Just pause the debugger, find a reference
to your dynamic animator, set debug enabled to true,
and you will have this great overlay depicting all
Now in addition to debug enabled and disabled,
we are also offering debug interval.
And this is a way that you can tune how often we update
that debug overlay.
So, by default, that will be updated
on every animation frame, but if you have a lot
of complex physics, it might be beneficial to change
that to five, for example,
to only update the overlay on every fifth frame.
And, we're also allowing you to adjust the animation speed
of the dynamic animator.
Now this might be helpful for slowing down things
to observe what's actually going on.
And then it's important to keep in mind when using this,
this can affect the results of the simulation,
when you slow things down.
So always ensure correction at 1x.
So, next, let's talk about UIDynamicItemBehavior.
Now, if you recall, this is a way
to alter the physical properties of your view or a dynamic item,
and it can be applied to one or more dynamic items.
And in David's example, he applied a lower density
and a higher resistance to the FaceTime square
to make it really stick to the field corners.
So a few more examples of the existing properties here.
We have elasticity, friction, we saw density and resistance,
we have angular resistance, and these are all great ways
to adjust how your item feels in the animation engine.
In iOS 9, we have added two additional properties: charge --
this affects the degree to which your item participates
in our new electric and magnetic field types;
and we also added an anchored property.
This one is a little bit different.
But what it does is it allows your item to participate
in the dynamic system, and participate in collisions,
but it will obtain no velocity of its own.
So it really behaves more like a collision boundary.
So next, I would like to talk about UIAttachmentBehavior.
And this allow you to constrain two dynamic items
such that they maintain a particular distance
from each other.
And you can configure this with the damping and frequency
to make it behave more like a spring as opposed to a rod.
And this is a great attachment.
You know, it's very useful, but it's really only one way
to constrain two items with respect to each other.
So, in iOS 9, we have added some additional attachment types.
The first of which is a limit attachment.
This is quite similar to the distance attachment
that we just described, however, instead of being constrained
by what could be thought of as a rod or a spring,
this one behaves more like a rope between the two items,
where the only constraint is a maximum distance
from each other.
And you configure this similar to the distance attachment
by specifying two points offset from each item's center.
Next, we have a fixed attachment.
And this one is a little bit different than the limit
or the distance attachment.
And you create this type of attachment
by first specifying an anchor point.
This anchor point is in the coordinate space
of your reference view, with respect to each item's center.
And this type of attachment offers no movement whatsoever
between the two items.
It's much like a welded rod between both items as opposed
to a rod that allows them to spin on the ends.
And we have also added a pin attachment type.
This one is similar to the fixed attachment where you start
by specifying an anchor point between two items.
But this type allows two items to rotate with respect
to each other, about this anchor point.
And this allows you to specify a rotatable range,
which by default would be unbounded but we could bound it
down to something smaller like so.
And finally we have added a sliding attachment.
Now the sliding attachment is a little bit more complicated.
We'll look at an example in just a second.
but just like the fixed and the pin types,
we first specify this attachment anchor point that's
in the coordinate space of the reference view.
But unlike those types, we also need
to specify an axis of translation.
And this is where all relative movement
between two items will be along the axis of translation.
And this type prevents all relative rotation
of the two items.
So they are really fixed rotationally with respect
to each other and they can only move along the axis
But just like the pin type,
you can limit this translatable range.
So if you do specify a translatable range,
it needs to include the attachment anchor point,
where the anchor point is defined
as the point zero in the range.
So if we set this system up with this type of attachment,
we can have linear motion
between the two items, like that.
So that's pretty complicated.
Let's look at a basic example.
And to do that, I want to return
to our sliding example one more time.
Now, I mentioned in the past, that had we tried
to make this slidable behavior, we would have had
to add a collision on the bottom and on each side
and somewhere off the screen above on the top,
to constrain the motion
of the sliding view along the vertical axis.
Well, with UI attachment behavior, we don't need to do
that anymore, we can use a sliding attachment to do that.
So we limit the system to one collision,
making the performance better,
and the code actually quite a bit more readable.
So if we enable our debug view here,
you can see the sliding attachment depicted
by the straight line along the vertical axis.
It expands and contracts as we slide the view,
but there's also another attachment there,
and that's a distance attachment that we use to attach
to an anchor point that's manipulated
by a pan gesture recognizer.
So, unlike David's demo, this one's entirely
within the dynamics system.
We don't disable or enable anything.
We just stay in dynamics.
So, finally, let me give you a quick update on UISnapBehavior.
If you recall, UISnapBehavior is a higher level behavior.
And it can be used to move a view from one location
to another with a snap-like effect.
And SnapBehavior allows you to customize the damping
of the snap, which can really adjust, you know,
the snappiness of how it feels.
In iOS 9, we've added the ability
to customize the snap point after init time
as well, which is pretty cool.
So let's look at a quick example, here.
So if we try to pan the view, here, with our debug on,
it will fall back to the screen, like the original snap point.
If we tap in another location, it will snap to the new point
and that's just adjusting the snap point
on an existing dynamic behavior.
And you will also notice that with the debug overlay,
this is actually a composite behavior of its own.
There's four attachments here, configured as springs,
just that snap the view to the new position.
It's really quite cool.
So that's what's new in UIKit Dynamics and iOS 9.
I would like to turn it over to David
to talk about visual effects.
DAVID DUNCAN: Good evening, everybody.
So we are going to talk about using visual effects
to add style to your application.
So we are going to motivate this
with just a simple image viewer application, where what we want
to do is show the user some extra information
about the photo they are currently looking at.
And so as you see right there, this image happens
to have a little overlay
that tells us what the file name is of the image.
So we are going to walk through how we actually create that.
And so, the first step is that you need
to create a blur effect.
And we have three different styles, the extra light,
light, and dark styles.
And then you create a blur effect from those styles.
And that's just how you do that right there.
And finally, you create your visual effect view
with that blur style.
Then you just add whatever layout you need to do
and you can get the blur that you see on screen there.
The next step is we are going to add a vibrancy effect.
And what vibrancy does is, it really makes something pop,
stand out from when it's over a blur.
And so what we are going to do is we are just going to create
that vibrancy effect from a blur effect.
As mentioned, it's really intended to be overlayed
from a blur, so we start with that blur effect
to create the vibrancy effect.
We create our vibrancy effect,
just like we did before with the blur.
And then, in this case we're going to add it
to the content view of the blur view.
Now, it doesn't have to be directly added to the blur,
but there should be a blur that you see behind
that visual effect view.
And finally, we add the label
to the content view of the vibrancy view.
And the reason we are adding these things to the content view
of the visual effects view, is because that ensures
that we get the correct effect for all the content
that you are presenting.
And so, when you have done all of that,
you get the lovely label on top of the blur
as you see on the screen.
So what's new in iOS 9 here?
Well, the first thing we have done is we have made it really
easy to cleanly animate the bounds of your view.
So that you can show more information in that blur view
to the user without having to do anything really complex.
But, in addition, we have made it possible
for you to animate the blur.
And so now, if you have a night load in your app, for example,
you can do a really clean animation from day to night
in your application and move the user along.
Now, the next thing we are going to talk through, briefly,
is how do we actually get these effects to the screen?
What does it do and why do you need to know?
It's important because this all has impacts
on both performance and correctness.
So little baby Sophia here is going to walk us
through adding a little overlay to her little UI here.
So the first thing to do is figure out,
where are we capturing?
Whenever we see a visual effect,
we figure out what the capture content we need for it is
and we move it offscreen.
So we copy that little piece out.
And now that it's offscreen, we can actually work with it,
but why did we take it offscreen?
Well, for one reason is that we need to make sure
that we get the correct effects and in this case
that we capture everything we need to blur
for that blur effect, but also we often do these things
offscreen so that we don't mess up the content that's already
on screen when we are doing effects like this.
So we apply the blur to it.
And finally we copy it back into position
where the effect view desired it,
and all of this is the definition
of something you might have heard before called an
It's whenever we take content, we copy it into an offscreen,
do work, and then bring it back on screen.
So what are some other ways that we can get offscreen passes?
Well, as you can see, we have got alpha,
and you can see the way you do that because
if you have a complex view hierarchy that needs alpha
in it, then we can't just apply the alpha to individual views,
because you won't get the correct effect.
Instead we need to take the entire complex hierarchy
offscreen, render it, and then apply the alpha
to the whole thing.
Masking has a very similar reasoning behind it,
in that we need to have all the pixels for the mask.
As we just mentioned, blur and vibrancy also go offscreen,
but snapshotting, why is that up there?
You might ask yourself.
Well, first off, what is snapshotting?
We have got these two UIView methods, snapshot view
after screen updates and draw view hierarchy in rect and
and the UIScreen method snapshot view after screen updates,
and these all hand you back content from a snapshot.
Well, a snapshot is basically doing the same thing
as an offscreen pass but giving you control over the final step
of copying it back to screen.
We take all content that you asked us to snapshot,
render it offscreen, and then hand you back a view
or pixel content representing that image.
But, again, what does this have to do with making sure
that your effects are correct.?
Well, unfortunately, if you get a visual effect caught in all
of this, as you can see, Sophia has lost her blur.
And that's what you will see on screen if a visual effect ends
up getting caught in an offscreen
that you didn't expect it to go into.
So back to motivating this, I'm sure you have all been
to the multitasking sessions this year, and if not,
you should watch them on video afterwards.
But one the key things that you need
to have a great app participating
in multitasking is good performance on screen.
Because now the performance
of your app also affects the other side app.
And so, since we don't have any scrolling
in this particular example, we have decided, let's instead
of keeping the blur rendering all the time,
let's just take a snapshot of it.
And so we decided to take a snapshot
of that particular visual effect view.
But then what happens is the capture area is
And since you only snapshotted the visual effect view,
there's nothing in that capture area.
And so the capture gives you back nothing,
and the blur has nothing to blur,
and you get the broken effect you saw before.
So, now that we have seen how you can have your effect broken,
what can we do to fix it?
Well, first thing is, we have this handy method
on visual effect view, called, what's wrong with this effect?
Just like with the dynamics debugging flags this isn't
available in the SDK as such, but you can call it
from in the debugger, just like this,
and you will get back a string that looks kind of like this.
In this case, we found that there was a mask view somewhere
up in the hierarchy that was causing the visual effect
to go offscreen, and thus not capture as much content
as it needed to, to render properly.
So how can you fix this?
First way that this works, if you are using either alpha
or masking, is to rearrange your view hierarchy.
What we have here is just some container, maybe the window,
and a container view
that contains a blur and further contents.
Well, in this case the blur doesn't actually need
to participate in the alpha or masking we have,
so we just rearrange to have the blur as the first subview,
the container as the second subview, and thus the container
and everything in it will render on top of the blur,
and we can apply alpha or masking to the container view
without messing up our blur.
A second thing that we can do for masking is,
instead of masking the container view, we can move that mask
down into the content that we actually need masking for.
Now, as we mentioned before,
masking will often take an offscreen pass,
so you should be very careful about performance
when do a transformation like this.
Finally, with snapshotting, as we mentioned before,
snapshotting is only going to capture what you tell it to.
So, in this case, that content view that we are asking
to snapshot has transparency in it.
So we can see things behind it.
But if we snapshot just that view, we aren't going to get
that in the blur and it is going to look a little funny.
So if we move the snapshot up,
all the way to the window is usually the easiest thing to do,
but sometimes you might need
to move it all the way up to the screen.
So if you are going to snapshot blurs, you should make sure
that you snapshot as far away from the blur content
as possible so that you are sure you get everything you need
And so with that, let's switch over to some best practices
with dynamics and AutoLayout.
So, the first thing you might do is you might have fairly complex
view hierarchies working inside of dynamics.
And what you want is for the outer view to participate
in the dynamic system but not the inner views.
They are just going to be laid
out like you would with any other thing.
So you can use UIKit Dynamics for the outside view,
just by turning translate auto resizing mask
into constraints to true.
And, yes, in the only slide at WWDC that says true.
And then you can use AutoLayout
to just position everything else inside,
just like you always have, or using the new syntax
as shown on the slide.
Another thing you can do is, often you will have items
in the dynamic system but you might have labels for them
that shouldn't participate, but they need to follow.
And so Lola here has her little tag
that says what the file name is, and we just have this anchor
that represents our AutoLayout constraints,
and then when dynamics comes in and wants to move Lola around,
the label moves with it, but the label does not end
up interacting with dynamics.
Finally you can work with dynamics
by creating a custom dynamic item,
just as Mike mentioned earlier.
You just subclass NSObject
or some other appropriate object class,
conform to the UI Dynamic Item protocol
and provide the required methods.
A bounds some of size --
it can't be 00, or the dynamic system is going
to throw an exception -- and you implement center and transform,
and you use the values of those in order
to construct AutoLayout constraints
or otherwise change something outside of your system.
And so to close out, we are going to show you a demo
of how you can do just that.
So what we have got here, is, again, a simple application
that just shows a photo.
But we want to be able to show the user the faces
in the photo with some style.
And so when we click our dynamic item system stretches out
and animates in that blur.
And if you click again, of course, it will move
out with a nice little effect.
But if you keep clicking, then you can see
that it responds very fluidly to the dynamic system
and doesn't have very set, rigid path.
So it's very reactive to exactly what the user is doing.
So how do we get that to work?
So, the first thing we do is we have this face layout guide,
and that's just a subclass of UI layout guide,
and inside of it is a little bit of dynamics.
We have this face layout guide dynamic item, that, again,
subclass as NSObject and conforms to UI Dynamic Item,
and it's going to manage a constraint,
and by setting the constant of that constraint to either the x
or y value of the center point, whenever that changes.
And then in here, when you set up the layout guide,
it's got a centerrable position
and it creates four additional dynamic items
that represent the top, left, bottom,
and right in that system.
We assign it the constraints and the constraints just work
from the top left corner of the dynamic item,
of the dynamic item reference view,
and we use slider attachments to limit
where those four dynamic items can go
with respect to the position.
And this keeps it from flying outside of the system
or collapsing to too small of a position.
Now, in the view controller,
the way we get this behavior is we have a gravity behavior along
with the face layout guide,
and we center them on top of each other.
So when the gravity changes,
the layout guide will move appropriately,
and we get the blur effect from our storyboard,
so that we don't have to constantly twiddle with it
if we decide we want to change the style we are using.
And we use constraints to attach that blur view
to the face layout guide.
So that when that guide changes size,
the blur view will also change with it.
Now, in order to make it look like the blur view is cutting
out everything but the faces, we actually have a little trick.
We make imposters from the original image,
just cut out the images that we want, apply a mask to them,
and create additional UI Image Views to place on top
of the one that's already there.
And so it looks like the blur is just dodging the faces
but what is actually happening is you're seeing the views
that were placed on top that have the faces cut out on them.
Finally, we have this tap gesture recognizer that we set,
and it will be the thing
that causes our dynamic system to change.
When we want to expose the faces,
we just change the gravity.
So normally the gravity is causing everything to be pulled
into the center, but then when we flip it,
it wants to push everything out like a repulsor.
And then we take advantage of the fact
that we are always laying out subviews during this,
to actually trigger the blur animation in or out.
And that's all it takes in order to build this really nice effect
from something that both autolayout
and dynamics can both provide easily for you.
And so we will go back to slides to finish out.
So in summary, we want you to use these technologies
to really improve the user experience.
So when you add a blur, you add it
so that you can put additional information offset
from your content.
When you use dynamics, it's
so that you can have a user interface that responds nicely
and as the user expects to their input.
But you also want to consider performance
when you are doing these things.
Because if you have a lot of dynamic items on screen,
that can really bog down the user interface,
and you don't get the nice physics that you were expecting.
So use it with caution.
But also for visual effects, if you have a lot of them,
you will end up with lots of offscreen passes
and that can incur quite a cost as well.
So these are all the related sessions
that we have got for you today.
Unfortunately most of them have occurred before.
There's only one that hasn't and that's occurring with us,
called "Building Responsive and Efficient Apps with GCD."
And we will be in the lab after this to take all
of your questions and help you get the most
out of what you have got for this year.
We have got various documentation, and assemble code
for the StickyCorners sample that you saw earlier
in the presentation should be up and available, and, of course,
Curt Rothert to take your questions through email.
And I'm glad you stuck with us on Friday.
I hope you had a great WWDC and a safe trip home.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.