Transcript
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Silence ]
>> Olivier Gutknecht:
Good afternoon.
[ Applause ]
And welcome to this WWDC session
on getting started
with UIKit Dynamics.
We think we have a great new
addition to UIKit for you today.
My name is Olivier Gutknecht
and I'm a frameworks
engineer in the UIKit team.
And you might have noticed
that on iOS 7, content is key.
And we'd like to offer you new
ways to have better rendering
and interactions
with this content,
and that is what
dynamics is about.
What are we going
to cover today?
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
First, the core concepts in
architecture of dynamics.
And dynamics is based
on a very simple ID,
combining basic behaviors.
And we've see how
you can actually use
that to integrate
new rich interactions
in your applications.
But first, I'd like to make a
very quick recap of animation
and interaction on iOS today.
Of course, almost everything
we render and animate
on iOS is based on
Core Animation.
Core Animation is an
amazing animation framework.
It has very strong
and consistent model,
extremely powerful API.
And on top of that, in UIKit,
we built UIView animations.
Easier to use API, web
integrated with the UIKit model.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And we actually include
that a lot in iOS 7.
We had it at UIView level
keyframe animations.
And we are adding spring
animations to UIView animations.
Another great API we have
in iOS 7 is motion effects.
A way to animate content
based on the physical position
and movement of your device.
That's how we build this
power act effect in iOS 7.
And when you start
interacting with content,
one great tool is
gesture recognizer
and drive changes
view moving based
on gesture recognizer callbacks.
But, you can also use lower
level APIs like CADisplayLink
and animate things at
screen refresh level.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And of course, you can actually
combine all of these techniques.
So, what is UIKit Dynamics?
I think somebody said yesterday
that this definition was
not exactly crystal clear.
It is a composable,
realtime system.
It's made to be--
you can subclass it.
You can combine effects
together,
and it's physics-inspired.
What kind of applications
can you build with that?
Well, maybe not.
Hoever that was probably
the most creative
and completely wrong
use of UISwitch ever.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
No, and why not?
Because we have much
better tool for you.
Sprite Kits, it's a
great new game framework.
It's available on iOS and OS X.
It's a great foundering engine.
And we actually use the
same physics engine.
So then, where can you use
dynamics in your applications?
I have a very quick demo
I'd like to show you.
This is a very simple
likable example.
I can organize my pictures.
And, as you pay attention,
when I'm dragging a picture
by the center, it
moves as expected.
But when I drag by the
corner of this picture,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
it will react the
way you would expect
when dragging something
in a table.
So we have natural real
world looking interactions.
I can select pictures to
the bottom of the screen.
I can throw this to
start organizing things.
But, maybe we can find
something easier actually.
So let's create new albums and
start organizing these albums.
OK. That's -- that's
much better.
So that's a good
example of using dynamics
in a non-game application.
So of course, that's
a WWDC demo app.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
How complex is that?
Actually, not that much.
You enter your application,
all implementation
files and no cheating.
It's about for 400
lines of code.
But what's interesting here
is I have a lot of code here
to load these images, have
this nice picture views.
The actual interaction code
is about 80 lines of code.
So that's really easy.
And most of it is in
this cute magnet effect.
[ Applause ]
So, let's start exploring
dynamics.
But first, why?
We wanted to provide a way
to [inaudible] model real
world inspired interactions.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And we wanted also
to provide a way
to combine quick
canned animations,
predefined animation
and interactions.
And we wanted to offer you
something that's really was
at UI level.
And there is a good example
of that, the lock screen.
In iOS 6, do you
still remember iOS 6?
OK. In iOS 6, when you
tap this camera button,
you have the small
bounce animation, right,
to show there is actually
a Camera UI behind.
And then you can drag, so
that's going up to review it.
And you can actually end
that gesture or cancel,
and the lock screen
is going fall down.
What's interesting is, in iOS 6,
these two modes are
completely separate.
There is a predefined animation
for the tap bounce effect.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And because it's a
completely predefine animation,
you cannot catch with a
gesture the lock screen
in flight while it's animating.
And seen in iOS 6, when you end
that gesture interactive part,
the lock screen just animate
down, it doesn't bounce.
That's not what we want.
So in iOS 7, let me show you.
So that's when I tap
the camera button.
I slide up and cancel,
it bounces.
I slide up and I'm going
to [inaudible] the view,
the bounce is slightly
different.
So that's a good example
of [inaudible] interaction
you might want
to add in your application.
How? When we start to
thinking about this API,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
an interesting question was,
where should we add that?
And one idea was, "Maybe should
just add new methods to UIView,
like setMass, applyForce."
That's interesting,
but we realize that's not
what you want to express.
You want to express
high level effects.
You don't want just
to mess with these use
and forces and everything.
You want a high level more
the clarity of expression
of these interactions.
So then, we ask the concept we
use all over the place in UIKit
and in all of our
frameworks' composition.
And in dynamics, we
compose Predefined behaviors
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
for you own behaviors.
In this lock screen
example, the bouncing,
falling down and
bouncing effect.
Why do I really need
to express that?
I need gravity towards
a view falling.
And I need a collision to
get this bounce effect.
So, in dynamics, I would express
that as one view being popped
off two primitive behaviors,
gravity and collision.
And all these behaviors ran are
associated in animation context.
So if we start digging
in the architecture,
what we add is first that's
new class, UIDynamicAnimator
which provides the context, and
then you associate behaviors,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
UIDynamicBehavior
subclasses to this animator.
And usually then, you associate
views to these behaviors.
And one key concept here is,
usually, you want to view
to be part of two or more
behaviors 'cause that's going
to combine the effect
of these behaviors.
The other thing we need is
what we call Reference View
which was a way to define
the global coordinate system,
in which we would
run this interaction
with the only constraint
that the views we animate
are actually subviews or part
of the view hierarchy
of that reference view.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So that's-- see in more
details what we have
in animators and behaviors.
UIDynamicAnimator provide
your overall context
for your animation and
defines the coordinate system.
And we'll see later,
that's quite interesting.
And it wraps the underlying
engine and we know when to start
and stop that engine for you.
It also keeps track
of all the behaviors
that are currently
associated with this animator.
It's really easy to use.
You just create a
UIDynamicAnimator
with the reference view
and then you just have
to add behaviors to that.
Behaviors.
UIDynamicBehavior is
something that is going
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to be associated
with DynamicAnimator.
It's usually associated with
a view or a set of views.
And we try to make behaviors
as declarative as possible.
It will describe some
inference view like
"That view should be
impacted by gravity.
That view should collide."
And a real interesting thing
about behaviors is you can add
and remove behaviors to
the animator at anytime.
And we'll see why that's a
real key concept in dynamics.
It's made to be composed.
You can actually group behaviors
together to define your own,
also by defining in
your own subclass.
And it's really easy to use.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Usually, you just want
to allocate-alloc init
a behavior usually
with a set of views.
And you add that
behavior to the animator.
And to help you, we
are providing in UIKit
in iOS 7 a set of
Predefined behaviors you can
combine together.
All of these behaviors
have some common traits.
First, usually, these
behaviors are configured
with items you want to animate.
Most of this, actually you can
add or remove views at anytime.
So if I want a view to be no
longer impacted by gravity,
I just remove it
from that behavior.
You can configure a behavior
before or after adding it
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to an animator and the influence
of a behavior stops as soon
as you remove it from
the animator itself.
So what do we have?
gravity, we talked about that.
collisions.
Attachment, a way to
connect views together.
We have a high level of behavior
we call the Snap behavior
which is a way to
snap view into place.
We have a behavior,
a Push behavior
to apply forces to views.
And we have a low level
behavior which gives you a way
to twitch some physics
level properties of views,
like friction, for
instance, or density.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So, let's explore this
Predefined behavior.
First one, Gravity behavior.
So if the only thing I have
in my animator is a gravity
behavior with just one view,
what's going to happen is
that, which is expected.
It's defined by a very simple
gravity vector which is uniform
and global to the
entire animator.
We have four views which
are part of this behavior.
And it's controlled by
x and the y components.
It's expressed in the
UIKit coordinate system.
So, (0,1) which is the default,
is gravity pointing
down which is nice.
And you can add and
remove items at any time.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
It's quite easy to use.
You create a Gravity
behavior with a set of items
and you just add this
behavior to your animator.
Through this one open
question, though, (0,1),
which units do we use here?
Well, there was a well-known
constant about gravity,
Earth gravity, 9.80665
[inaudible].
Who designed this API?
UIKit Gravity, much better.
One thousand points
per second square.
It feels like Earth
gravity, trust me.
Just easier to use
points on devices.
[ Applause ]
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Collision behavior, that is
a really interesting one.
You just add a view.
You can specify a boundary.
And in this case, I
actually added gravity
because without gravity, that
would not animate, right?
So, another mode is
colliding between views.
And of course, the third way
to use Collision
behavior is colliding
between views and boundaries.
Views are controlled by a very
simple property, collision mode.
UI won't views to collide with
views, views to only collide
with boundaries but
not with other views,
or a views colliding with
views and boundaries.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Like gravity, you can
add and remove items
from this behavior at any time.
So if I actually make a
bottom green view disappear,
what's going to happen is we
will resume the animation.
And I was talking
about Composition.
The real interesting use case
here is you can define multiple
Collision behaviors, so you can
express really easily things
like I want red views to
collide with red views,
green views with green views,
but not green views
and red views.
And a small word of warning
here, it's not completely free.
We steer around an
engine [inaudible],
so collisions do have a
cost we have to detect,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
compute when we have collisions.
Boundaries.
How do you create this?
There is a really easy way
which is having what you want
which use that reference view
we were talking about before
as the default boundary.
So that's a really
simple property.
We have a variant which--
with which you can
actually apply in sets.
And we have another way
to define boundaries.
So you can do things like
that by defining segments
or even path, UIBezierPath.
In that case, you have to know
that we basically approximate
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that with a set off lines.
But usually, it's OK.
When you create this, you
need to pass a notifier
and we will see why
in a few minutes.
And again, you can create
a multiple behavior,
multiple boundaries.
There is one thing
in these slides.
I did show you the
boundaries I was using.
On device, the only thing
you see is that view.
These boundaries are just
description of my system.
They don't have an
existence on screen.
We have an interesting
delegate on Collision behavior.
And you can be notified when
we actually have a collision.
So, when a view collides
with a view,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
you can implement this
method and you will get
where that collision took place,
and same thing for boundaries.
And this is why we have
this boundary notifier,
so you will know which
wall you collided with.
And by definition,
when you get nil,
it was this reference bounds
easy way to set up boundaries
and that is implicit
bounds we pass nil.
Next, Attachment behavior.
This describe a view connected
to an attachment point
and it's really easy to use.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
You just pass a view and
where that one should be
and that's expressed in the
reference view coordinate space.
We have a variant for that
where you can actually
connect two views together.
So in this case, imagine that
I then push that middle view,
the system is going to
react as you would expect.
You can even specify
where that connection is.
You can specify as an offset
from the center of the view
where we should attach this view
or these two views together.
There is a nice feature
in UIAttachmentBehavior.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Springs. You can configure an
Attachment behavior as a spring.
[ Applause ]
Just pass a Frequency and
Damping and it will act
as a really easy
to set up spring.
Another interesting feature is
that attachment point
can be moved.
So if I move the attachment
point, the view is going
to move as you would expect.
We also have a length
property that you can change.
Usually, you don't need
that because we compute
the length at init time.
Sometimes, you need that
but you have to know
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
when you change just in one
shot, the lengths of something,
it's not really physically.
So, it's really not
a common case.
Like boundaries,
these attachments are not
visible in your application.
It's just description of how
your system should react.
I'd like to show
your how it feels.
[ Pause ]
So in that example,
I actually added code
to show you the collision
boundaries
and the attachment
because, without that,
it would just be a view moving
in a very strange
way of the screen.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So, again, to start with
a very simple attachment.
So that's my gesture.
So it really acts
like a nonflexible small
rod connected to this shape.
There is no gravity, so it's
like that's green shape
was just flat on a table,
so I can push or
pull that shape.
All right.
And, the other mode we have for
Attachment behavior is Springs.
So, let's see.
It's just the same thing.
I can actually push
that view or pull it.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And just because of
that Spring effect,
you don't have exactly
the same animation.
[ Pause ]
Snap behavior that's
a high level,
really easy to use behavior.
It just snaps a view at specific
place on the screen and we try
to get it back to
non-rotated state.
It looks like that.
Really easy to use.
Oh, you can actually customize
also that dumping effect.
One way to understand
the Snap behavior is just
like if we had set
up four small springs
at the corner of that view.
To create a Snap behavior, you
just pass an item and a point
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
in the reference view coordinate
system, and you just add
that Snap behavior
to your animator.
Push behavior, that's
a way to apply forces.
And, you just want to set
up a Push behavior
with a set of views.
And there is this
mode parameter here.
What does that mean?
It means that, in this mode,
we're going to apply a force
which is the force will
still be applied while
that behavior is
active in the animator.
So, which means that for
this view, the view is going
to accelerate, right, 'cause
I keep applying that force.
It's defined with a very simple
force vector, xComponent,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
yComponent, or magnitude
and angle, if you prefer.
And there is another
interesting feature here.
You can actually
customize where,
in that view, we
apply this force.
So it's an offset
from the center
of the view which
is the default.
And if you apply a
force small offset
from the center is still being
to push that view but you want
to get this rotation
effect at the same time.
Units, we have a well-known
unit per force Newton,
which is defined as the
amount of force you need
to accelerate 1 kilogram to
1 meter per second squared.
[ Pause ]
[ Laughter ]
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
UIKit Newton.
Accelerate to 100
point by 100 point view
with a default density to
100 point per second squared.
Should we give it
a name on UIKit,
[inaudible], I don't know.
You don't-- we don't need a
name actually 'cause it's really
in Newton.
Observe that we are expressing
it in the UIKit unit system.
There is an also
interesting feature
to UIPushBehavior what we
call the instantaneous mode,
immediate mode.
In that case, instead
of applying a force,
we just apply very
quick impulse,
which mean that this view, we
immediately acquire a velocity,
it's not going to accelerate
over time it will just
kick it a little bit.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And it's going to
automatically visible itself
after applying it.
And if you want to
reenable that again,
we have the Active property.
And you can set that to
Yes again and you would get
that [inaudible] force again.
That's a great way to actually
implement this tap Camera button
in the lock screen.
So we have gravity.
Push behavior in force mode.
Push behavior impulse mode.
One is immediate
velocity change.
The other one is
accelerating the view.
How could we see how that
works and understand better?
Science. We should
grab some graph paper,
run some experiments
and see what happens.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
We're going to do exactly that.
[ Pause ]
So, the first setup here is two
views which we're going to add
to a Gravity behavior.
In that case, the
relative size or density
of the view will not matter.
So, these views are just going
to accelerate the big one
and the small one
at the same rate.
Now, Push behavior
in continuous mode.
So we will apply the same
force to these two views.
These two views will
be part actually
of the same Push behavior.
One is smaller than
the other one,
so it's actually easier to use.
So it's going to
accelerate faster.
Let's verify that.
Yup, that's correct.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And the third mode is Push
behavior in instantaneous mode.
That's just at a very
quick impulse these views.
So, as you see, these do
acquire a velocity but then
that velocity doesn't change.
These views are not
accelerating.
So if we run everything again,
it feels like the last views are
actually decelerating but not.
It's just an effect
of the other view
which are indeed accelerating.
So, that's difference
between Gravity
and the two modes we
have for Push behaviors.
[ Applause ]
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
UIDynamicItemBehavior.
This one is the last
Predefined behavior we have.
It's a little bit strange.
It's more acting as a template
you can apply to your views.
With Dynamic Item Behavior,
you can actually customize
properties to one or many views.
And what we have is friction
when views are sliding
one on top of the other.
We have dumpingResistance
and angularResistance.
And that's useful
because without dumping,
views would just keep moving
which is usually the feel
you don't want in a UI,
so we have a default
dumping set on views.
Another interesting
one is elasticity
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
which is the restitution when
you collide to the bounciness.
And density which is a
way to actually set a mass
or a relative mass
between views.
So, we cheat.
We don't offer you set mass.
But we do offer you set density.
Fair enough.
And the last one is-- whoops.
So that was-- the right view was
part of a UIDynamicItemBehavior
which actually changed
the elasticity property,
so it bounce more.
And we have one last property
which is interesting for UI
which is allowsRotation which
is basically a way to cheat
with the underlying engine
and to actually block rotation
of the items we animate.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
There is another really
useful low level method
in UIDynamicItemBehaviors,
that's a way to immediately set,
immediately add a given
velocity to a view.
And why is that useful?
Sometimes, your interaction
with dynamic starts
after a regular gesture-based
interaction.
And in this case, you add
this seamless transition
from the gesture-based
phase to dynamics phase,
you want to exactly match
the gesture velocity.
So you can actually inject in
the system with this method,
the gesture velocity itself.
That's really useful.
And, 'cause we use
the UIKit unit system,
it's expressed in
points per second.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Applying Dynamics.
So when you want to add dynamics
through repetition,
what do you need?
First, you need to know which
views you want to animate.
You want to define
what is this container
or reference view you would
create the animator with.
And then it's really about
creating the behaviors you need,
adding views to these behaviors.
Next thing is configuring
if needed these behaviors
and associating these
behaviors to animators--
to your animator, and that's it.
As soon as we have a view in an
active behavior and we detect
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that the system is not
at rest, we reanimate.
The other thing is when we
detect that the system is
at rest, we stop animating,
which means that we
basically stop the engine,
we stop the CADisplayLink
we use on those [inaudible].
So, a system at rest is
not consuming CPU at all.
Well, this is physics.
So, you can actually
create with this API setup
which don't really make
sense, like if you say
that this view should
collide with that boundary
but if the initial state of that
view is completely intersecting
with that boundary, you won't
really have animations, right?
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And we are going to be
slightly confused about that.
And also interesting variant
with Collision behavior is
if you try to add
all these views
in this very small enclosed
space, it's not going
to work 'cause we basically
can't compute a correct solution
for that setup.
And in all-time coverage,
when you have a view blocked
by a boundary and you try
to apply an infinite force,
this will not break your device.
So, when I-- what
I usually suggest
when you're building
systems with dynamics is
to build that step by step.
Start with one behavior,
add your views,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
configure that behavior,
see how that reacts,
add another behavior, see
what's changing, see--
check if the actual
interactions feels right,
and then keep adding or
tweaking your behaviors.
If you start by constructing
this incredibly complex set
of behaviors in the
configuration
or the [inaudible], and
if that doesn't work,
that's not really easy
to actually understand
what's [inaudible].
So in this case, just remove
one-by-one your behaviors
to understand which one was
actually causing the problem.
Did I mention that we are
sometimes cheating with physics?
This is not a physics-accurate
simulation tool.
Do not use that to control
your Evil Genius Space Station.
That is your configuration that
we do not support explicitly.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And that's really a core
concept of dynamics.
But I'd like to show you
a few additional things.
The first one is what
we call Dynamic Items.
You may not notice that,
in this presentation,
I was talking sometimes about
views, sometimes about items,
sometimes-- most of these
methods actually were init
with items.
So, views or items?
UIDynamicItem is
actually a protocol.
And what's great about that
is it describes what we need
for something associated
with a Predefined
behavior to be animated.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And what UIKit needs
to animate something
in dynamics is actually
pretty basic.
We need to be able to
actually move an item.
We need to know the size of
this item because we need
that for correct forces,
computation, or collisions.
And an object without a size
is again not really physics.
And we need to animate
a rotation
because the only thing we
animate is 2D rotations.
Guess what, UIView actually
implement that UIDynamicItem.
Center, transform,
bounce, that's all we need.
But because of that's
actually a protocol,
you can implement that.
You can define your
own dynamic item.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Your own classes
implementing UIDynamicItem,
and we will just call center
and transform on this.
It's actually a really
simple protocol.
I can add everything
on just one slide.
The thing we need is we need
to know the initial
state for an item.
So we need to know the position.
We need to know the size.
We need to know the initial
rotation only to the rotation.
And then, when we animate
on each [inaudible],
we basically call
center and transform.
And that's how we
animate things.
Actually, there is another class
in UIKit when you set a position
to transform and which has a
size, and that's not UIView.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
CollectionViewLayoutAttributes.
You can use dynamics
which UICollectionView
and the way it works is
UICollectionViewLayoutAttributes
which is what we use when
you define your own layout
to describe where a given cell
is going to add on screen.
That class we introduced
in iOS 6 actually
implements UIDynamicItem.
And when you want to
create an animator
to actually animate parts
of a layout, you just create
that with the layout
itself instead
of passing a reference view.
For the layout is going
to define a size
CollectionView button size
and that's all we need.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And then when you want to
create your own behaviors,
instead of passing views,
just pass your
UICollectionViewLayoutAttributes
instances.
And we're going to animate this.
And because you passed through
layout at alloc-init time,
we will derive the layout
in validation itself.
Which also mean that when we
detect that a system is at rest,
we want to invalidate
your CollectionViewLayout.
So that's Dynamics
and UICollectionView.
[ Applause ]
And, because that's
the last demo,
I'm going to do something
a little bit silly.
[ Pause ]
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
That's a CollectionView.
Actually, that's a subclass
of a well-known
UICollectionViewLayout.
You might know
UICollectionViewFlowLayout.
Well that was just
a subclass of this.
And what can you do
is a CollectionView
with a data source
in a CollectionView.
You can add new elements, right?
So let's do that .
[ Pause ]
[ Applause ]
[ Pause ]
To conclude, UIKit Dynamics is
really an interaction-oriented
animation system.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
The best way to use dynamics is
to create this small
additional effects are going
to make your application
more alive
and have this natural feel.
And that one good thing
to keep in mind is
to notify your key
elements and animate this.
Again, it's really about
focusing on the user experience.
What can make your
app even better?
We have UI Dynamics
recommendation
in the UIKit Prerelease Library.
We have another session about
UIKit Dynamics and I'm going
to explore how to create real
effects by combining behavior
and creating your own UI
Dynamic behavior subclass.
We have some related sessions
custom transition using
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
View Controllers.
And you can actually
use dynamics
with View Controllers transition
[inaudible] about that.
And we have-- or
if you're indeed,
game oriented two
sessions about SpriteKits.
We have a dedicated dynamics lab
[inaudible], come talk to us,
and we can't wait to see what
you're going to do with that.
Thank you.
[Applause]