WWDC2013 Session 226

Transcript

X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Silence ]
>> Hey, Brandon.
>> Hey Jim, how's it going?
>> Oh, it's going really well.
I just got the DemoApp done
for this presentation
about 15 minutes ago.
>> Oh, that's great timing.
I have a 50K run this weekend
that I really wanted to use it
for to get some pictures.
What features have you
put together so far?
>> Well, I got the basic
functionality working.
When you have the phone taped to
your chest while you're running,
it's going to take a
photo of what's in front
of you every three
or four seconds.
And then when you're
done with your run,
you could show the photos
to your other runners
and there's some basic
editing functionality
like you can delete
photos that were blurry
and you can set favorites
as a background.
>> That's great.
So, I know you probably haven't
done much on the user interface
yet but that's really
a good thing
because we just got some brand
new specs from our designers
to make our app look
great on iOS 7.
>> Oh, good.
>> Let's take a look at them.
>> Cool.
>> So, here's what our designers
have put together for us.
We can have the ability to
view photos in our application
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and delete ones that
we don't like.
And I'd like us to do this
interesting custom delete
animation where we kind
of shadow the photo out.
>> Oh, neat, neat.
Kind of like a [inaudible]
effect.
>> Yeah, something like that.
I think it'd be pretty cool.
>> Cool.
>> They've also defined
some custom appearance
in our application.
They like our buttons to look
a little bit more interesting
with some special arts and
they've given us a tint color
for our application
to have its own style.
>> Excellent.
Yeah, I think the Appearance
API could probably help us
out with that.
>> That's what I was thinking.
They've also asked us
to do an interesting way
of playing back photos
in our application.
And they've put together
the spec that shows a kind
of a bouncing effect
where photos kind of fly
in from behind the user and,
you know, bounce off-screen.
>> Oh, that's a neat effect.
I have-- we'll see what
we can do with that.
>> I was thinking dynamics
that help with that.
>> Oh, yeah, actually,
that's a good idea.
>> Then the last thing
that showed us is
in our home screen
of our application.
They'd like to do some blurring
and they put together
this really,
really interesting looking
LensFlare that they'd like us
to drop on photos because
everyone loves LensFlares.
>> That one is a-- that flare
is a little [inaudible], man.
I'll see what I can do.
>> We'll see what
we can put together.
>> All right, cool.
>> So, why don't you go set up
the demo and I'll get started.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
>> All right, cool.
>> Cool. So, we're going to
talk about three things today.
We're going to start
off our talk by talking
about how we can do custom
view controller transitions.
After that, we'll move on to how
you can customize the appearance
of your application using
things like UIAppearance
and some new features
we've added to iOS 7
for making images look
interesting in your app.
Finally, we're going
to wrap things
up by spending some
time talking about how
to add realistic motion to your
application using UIKit Dynamics
and the new motion effect APIs.
So, let's get started by talking
about custom view
controller transitions.
This is something we've added in
iOS 7 that makes it really easy
for you to customize and
make unique transitions
in your application,
and we're using these
across the operating
system as well.
So, if you take a look at
a navigation controller
like this one in mail, this
is actually an interactive
transition where when
you start to scroll back
from the left-to-right
edge gesture, you notice,
the user can actually
interact with it and kind
of pull it back and forth.
And notice how the text
slides differently in the top
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and those two view controllers
move at different speeds
across the transition.
We create this using the
new view controller APIs.
These are great way to make
things look interesting
in your apps.
There's a number of things
that we allow you to customize
with those view controller
transitions.
You can customize
both the present
and dismiss animations review
controllers as well as pushing
and popping things off
of your navigation stack.
Now, in addition to
letting you customize all
of these different
types of transitions,
we're also giving you
the ability to make any
of them interactive
or non-interactive.
That way, you can decide if
you want just a fluid thing
that always happens without
the user touching anything
or if you want to build
something a little bit more
advanced like a navigation
controller
where the user can
actually feel it and play
with it as it transitions.
So, what do you need
to do if you want
to customize a view controller
transition in your application?
In this example, we have
our first view controller,
we'll call this our
two view controller.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
When we're ready to do
a transition into that,
that modal view visibility view,
we're going to create
a two view controller,
our photo detail view.
So now, we have our two view
controllers, the one on the left
that we're going to present
from, the one on the right
that we're about to
present to the user.
Once we've created
the view controller,
we need to specify the
transitioning delegate.
So, in this case, we're going
to tell our two view controller
that the transitioning delegate
itself are fromViewController.
That means our
fromViewController is going
to be responsible for responding
to how these transitions
need to happen.
Once we've set that up, we need
to go ahead and say we're ready
to present our view controller,
and we do that by saying
presentViewController
animated completion.
This is the same API
that you're used to using
for presenting the
view controllers.
But in this case,
we've specified
that you have a transitioning
delegate and that means
that the system is going to
have to ask you how do you want
to do that transition.
And we do that by asking
you for AnimationController
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
for presented controller,
presenting controller,
source controller.
That's a lot of controllers
going on there.
So, let's talk about what
those actually mean for you.
The first is the
presented controller.
This is what we're going
to actually be presenting
on screen.
It's the [inaudible]
we're about to present.
That's the two view
controller on the right.
Next is the presenting
controller.
This is what we're going to be
presenting from, in this case,
our fromViewController.
The final case is the
source controller.
The source controller in
most cases is the same view
controller that we're presenting
from but occasionally,
we have to do a little
bit of work to present
from a different place in the
view cart controller hierarchy.
So, we'll do the walking
through and let you know
if we're presenting from
a slightly different case
and we'll let you know that
with the source controller.
But most of the time,
you don't need
to do anything too interesting
with that particular argument.
It's there for your information.
So, we've been called
with a system asking
for this animation controller.
We're going to create a new
object, and that's an object
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that responds
to UIViewController
animated transitioning.
It's a protocol that you need
to implement on this object
that specifies how to
perform the animation.
There's two methods that
you need to implement,
transition-duration
and animate transition.
Transition-duration, as
the name would suggest is
to tell the system how long your
transition is going to take.
That way, we can time things out
and make everything work nicely.
Animate transition is
where you actually do all
of the animations.
So, that's where
you're going to want
to get the two view
controllers out of a context
and then you're going to need
to actually do the animations
that you want to have happen
to place your view
controllers on screen.
Once we've created that
object, we'll return it back
to the system and let
it do the transition.
To help you make this a little
bit easier in your applications,
we've created UI percent
driven interactive transition.
This is an object
that we're get--
making available in UIKit to
help make it easier for you
to create interactive
transitions.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
It lets you update
the transition
as it's happening based
on touch or other inputs
that might be relevant
to your application,
whatever makes sense for you
and creates a great
experience for your users.
And a couple of things that you
can vary while the transition is
happening is the completion
speed and the completion curve.
You can tweak the values of
those while the transition is
in flight to make an even
more unique experience
and a more unique
transition inside your app.
So, Jim, if you remember
what our designer specs,
they put together this
really great delete animation
where we kind of destroy
the photo that's on screen.
Have you had a chance to
put that together yet?
>> Well, I've got it started.
The animation isn't
quite complete yet
but I got the transitioning
stuff working.
You want me to show it to them?
>> I'd love to see
what you have so far.
>> All right, now here's our
exciting application that's
on the store today.
All right.
So, we have bascially,
we have some runs
that we've already ran through.
And I'm going to select
the WWDC run and want to go
and show all the photos that
we've taken from this run.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
This is obviously around
the campus and you can go
and select one of
your photos here.
That's a nice photo.
We have a basic presentation
right there.
And if you go ahead and
hit delete, you're going
to get a nice little-- it's
a nice little burning effect.
It's not quite what
we got there yet but--
the scanline goes up,
removes the images.
It's basic animation.
There's no real dynamics
that's into it yet.
It's doesn't move around a lot.
But, it's a basic-- the
transition is actually working.
So, let me go show you how that
actually is working so far.
So, the photos that you saw
there are in a collection view.
And so, in our collection
view, we simply--
and collection view's
delegate method
of didSelectItemAtIndexPath,
we're simply going
to create a new instance of
the edit photo view controller.
And at the next part, we're
going to go and create a couple
of properties that when you
set on that view controller
to basically do what
our app does.
We need to know which run we're
talking about and which photo
that we're interacting with.
We also have a custom
delegation callback that's going
to get called when that
user hits the delete button
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and that is to let us know
that the user deleted the photo
and it also dismisses
the view controller.
Now, the important part
of this when dealing
with custom transitions
are these two lines.
The transitioning delegate
is what's going to be asked
for if you have an animator
that you would like to use.
In this case, we do.
And the modal presentation
style has set the custom.
And it's not required
that you set up the custom
but in our case, we would like
to do that and when you set it
to custom, you get the
opportunity to place both the
from and the two view
controller on screen.
You are responsible for
both animating them in
and animating them out.
And then, obviously
represent the view controller.
Now, since we're just
concerned with the dismissal
of our editing view controller,
if the user deleted the photo,
we go ahead and we
create an instance
of our delete photo animator.
And if it's not being deleted,
we just use the normal
presentation animator.
So, let's go take a look at
what the delete photo animator
actually does.
Animation-- Transition-duration
is just two seconds.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Like Brandon, this just lets
the system know how long your
animation is going to take.
And then the second part
here is animateTransition.
Now, in this method, we're going
to pass you a transition
context.
And in this context is
everything that you're going
to need to know to
do your transition.
Not only do you get the from
in the two view controller,
you get, is this
transition animated.
You also get the ability to
know the from and to positions
of where we think
those view should land.
You also get a critically
important method you'll need
to call back called
completed transition.
If you don't call this
method, we don't know
that the animation
is actually finished.
So, your transition
will actually just hang
and I'll show you where we do
that here just a
little bit lower.
Now, there is a bunch
of animation code here
that really doesn't matter for
the aspect of transitioning, so.
But there are three points that
I'd like to point out here.
The first is that we don't
really care where the two view--
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
we don't want to animate it in.
We just want to place it
in its final position.
So, that is our collection
view coming back
as the front-most
view controller.
So, we just asked the
transition in context
for where we should place
that and we stick it
in the container view.
The second part is that
I'm using snapshotting,
the snapshotting API to
create those little tiny boxes
on screen.
That's an image view
that holds an image
and while we could have gone
through and re-rendered each one
of those boxes as its own image,
it's like an image
view in there.
The snapshotting API is
actually faster in that regard.
It's really performance
and it allows us
to [inaudible] those
little boxes into--
sort of create those little
boxes really, really quickly.
And unfortunately,
it's commented
out in the sample code
due to a name change
between Seed 1 and Seed 2.
So, I didn't want
to show errors.
But Brandon will talk
to a little bit more
about that after I'm done here.
Finally, going through a
whole bunch of animation code,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
it's this line right here.
When we are done
with our animation,
when the scanline is
completed to the top
and we're sufficiently happy
enough blocks have been
destroyed, we call
transitionContext
CompletedTransition and
in this, this system knows
that your delegate
transition, it can tear down all
of its context that it's
built up for you and then,
it will return back to
the two view controller.
>> That's looking great, Jim.
>> Thanks.
>> It's a really good start
on that custom transition.
I think I'd like
to talk a bit more
about snapshotting
now if you don't mind.
>> That's a good idea.
>> So, we've introduced
a fantastic new API
in iOS 7 that's called
UISnapshotting.
This is a major improvement
over rendering context
that you're used
to using for trying
to get snapshots of a view.
What we give you back with the
new snapshotting API is the
extremely fast representation
of the currently rendered
contents of your view.
We go really deep in and
pull that out for you.
And like I said,
it's extremely fast.
It's useful in a
couple of great places.
As you just saw, we can do
some really interesting things
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
with custom transitions and
the new snapshotting API.
It's also a great
tool for making some
of the new special effects
that you see across iOS 7.
So, how much faster is this
than rendering context?
To kind of demonstrate this to
you, we took a version of iPhoto
for iOS and we've asked it
to render in context as well
as using the new snapshot APIs.
As you can see, this is a pretty
complicated view to render.
If we render this with
rendering context,
it took about 840 milliseconds.
It's a really long time to
generate just a snapshot.
To compare that, when we use the
new snapshot methods in iOS 7,
we did the same in
56 milliseconds.
It's an incredible improvement
for you and you should be able
to make some incredibly
awesome effects
with it once you can take
advantage of it in iOS 7.
So, what does the API
for this look like?
There's two key methods that
you should take a look at,
snapshot view and
resizable snapshot view
from rect with cap insets.
Now, as Jim mentioned, it's
important to note in Seed 1,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
these methods are snapshot
and resizable snapshot,
they'll be this API you see
above for Seed 2 moving forward.
There's a third bit of API
for UISnapshotting though
that we've created for
a very special case,
and that API is
drawViewHierarchyInRect.
This will also be
available starting
in Seed 2 going forwards.
DrawViewHierarchyInRect is
still considerably faster
than rendering context
but it's not quite
as fast as snapshot view.
To give you an illustration
of that, we can compare
that on our usual
graph and rendering
that complicated view hierarchy
took about 150 milliseconds.
It's still considerably
faster than rendering context
but almost three times
slower than snapshot view.
So, why should you use this
drawViewHierarchyInRect?
Well, you've probably noticed
iOS 7 takes a lot of advantage
of these blurred effects
that you see behind toolbars
and navigation bars and so on.
This is your new API in iOS 7
to make static blurred effects
that look the same as what
we do across the system.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So, how do you do that?
The first thing you'll need
to do is call UIGraphicsBegin
ImageContextWithOptions.
This will make a new empty
image context with the size
that you asked for to
start rendering into.
Then you'll take your view
and you call
drawViewHierarchyInRect.
That will render
your views contents
into that context
very, very quickly.
Once you've done that, we
can get a new image out of
that context for
future processing.
That's as easy as
calling UIGraphicsGetImage
FromCurrentImageContext.
Once we have that image out,
we're done with the context
so we can go ahead, go ahead and
end that, clean everything up.
And then the last
part is applying
that blur effect to our image.
You notice I'm calling apply
light effect in the code above.
This is a category on UIImage
that we're making available
through a sample project
called image effects as well
as in the sample code
from this session.
Please feel free to
bring that category
into your own applications and
use it to apply light, dark,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and very light effects
across your application.
And that's how you can
make blurs in your apps.
Next, let's talk about how
to customize the appearance
of your applications using
a number of different tools
and techniques that we
have available on iOS.
So let's say, I have this
incredibly exciting application
with three sliders in it.
Now, I really don't want you
to rush out and like copy
that on the App Store.
This is all mine by the way.
So, our sliders default
to a blue tint color.
But my designer said, "We
actually want a red tint color."
An easy way to do this that
we'd have it for a couple
of years now is using
the appearance proxies.
These are as easy as
calling appearance on some
of the UIKit controls and then
setting various properties
on them such as tint
color, and that means
that whenever I make a
new slider in my app,
it will automatically
inherit these appearance set
of attributes.
But what if my application
has a lot
of different types of controls?
I don't really want to have
to call appearance on all
of these different controls
across my entire application.
There's a new change in iOS
7 to the tintColor system
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that makes this easy to
set a unified tint color
across your app.
When you call setTintColor
on say a window,
all of its subviews will
inherit that tint color
until something else lower
in the view hierarchy
overrides that.
So, if you like-- if
you would like your app
to have a standard tint color
of red across your entire app,
simply call setTintColor
on your window
and everything will inherit
that appearance, that attribute.
So, again, what do
these APIs look like?
The UIAppearance proxies
have been around since iOS 5
and you can call appearance
and appearanceWhenContainedIn.
AppearanceWhenContainedIn
allows you
to change your appearance based
on what your controls are
contained in, what kind of view.
We're changing tint color
and bar tint color in iOS 7
as I was just explaining
where tintColor will
impact things based
on your view hierarchy.
Bar tint colors appear--
it's not appearance,
its behavior has changed
a little bit on iOS 7
so that it's what you use
to specify the tint color
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of an entire bar on iOS 7 rather
than tinting the contents of it.
So that's how you can use
tintColor and appearance
to make your apps have their
own unique look on iOS 7.
We've also made some
changes to UIImage on iOS 7.
We've added this new method
called imageWithRenderingMode.
And there's a few
rendering modes
that you can apply
to images on iOS 7.
You can put them in
rendering mode automatic.
This is what we'll give you by
default where we'll do our best
to decide how to
render the images based
on how you're using
them in your app.
We're also allowing you to
customize these behaviors
with rendering mode
always original
and rendering mode
always template.
Now, these names probably don't
have a lot of meaning to you,
so I think I'd like to show
you what that actually means.
This is my original
image of Carl.
Carl is my friend.
If we want to render
Carl into my application,
if I put it on rendering
mode always original,
it means that we'll
render it exactly
as the original image was given
to us in all of his pink glory.
But if I switched it over to
rendering mode always template,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
we're only going to look at the
alpha channel of that image.
We'll ignore the red,
green, and blue channels.
We'll also take the tint color
of your application and apply it
to that template image.
So, if my application's tint
color is red, Carl becomes red.
Similarly, if my tint color
is blue, Carl becomes blue.
[laughter] The next thing
we'd like to talk about is how
to use resizable
images with cap insets.
In this example from
Siri on iOS 7,
I'd like to call your
attention to the movie ratings.
You notice, we say what
the rating of the movie is,
and we draw this nice white box
around the outside that's
very nicely fit to the text.
We create that with UIImage
resizableImageWithCapInsets.
In this example, I have
this very small image
for my designers where we have
these corners that we want
to keep the same shape
but we want to be able
to scale the image to be very
large or more medium size
without distorting the colors.
You do this by specifying your
cap insets for the left, bottom,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
right, and top to be how far
into the image that you want it
to always stay the same.
And this is made even easier
using the new asset catalogs
in iOS or in Xcode 5.
So, where's is this
a win for you?
This is a big benefit
in your app
because you can use a single
asset to style buttons
of all types of different
sizes across your entire app.
It also is a big win
for localization.
So, as you have text in your
application and you have buttons
with different lengths
of strings,
the buttons will
automatically and cleanly resize
to fit whatever string
your localization team puts
into the app.
So, going back to the specs from
our designers, they've asked us
to use these custom buttons
across our application
using a resizable image
and they've also asked us to use
a tint color of puce in our app.
Jim, do you remember what
the value is for puce?
>> Uh, 204136153.
>> Make it so.
>> All right, cool.
So, let's show you
what it looks like now.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
As you can see, we-- on
the first demo I had,
the buttons are already
in there.
So, they're still
already in there.
But now, they all have the tint
color that everyone so loves.
And then you know also the
navigation bar also has
tint color.
As we drill through the app,
everything that [inaudible]
to the tint color
already has it.
So, we changed one line of code
and our entire application
gets themed with its color.
And now, our designers actually
in our application wanted
to have backgrounds to
be blurred in some cases
and then not blurred in
other cases to give some--
just have a little bit
more polish to our app.
And you do that by
when you select one
of your favorite photos
in your application,
so let's go and choose that one.
And we go ahead and we'll
set that as our background.
And if you notice right now
that the segment it controls
also picked up the tint color.
And as I set the
background color,
if I set the background image,
the checkbox is also
a template image.
So it will also pick
up the tint color.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
As we go back, now we see
that our background
has a nice tint effect
or a blurring effect to it.
Excuse me.
And as we back up all the
way to the main screen,
you'll see that the buttons
are actually getting blurred
as well.
So, let me show you how we
go about doing those effects.
As Brandon mentioned, we wanted
to set a default button
background for all
of our buttons
in our application unless
we had set a specific--
some specific blurred
background.
And so, we won't go
into this very much.
But this is the code
that actually does that.
We get our default button and
then we make resizable image
with cap insets and we set a
5 point cap inset on the top,
left, bottom, and right.
And to give you some reference,
this is actually the images
I'm using and it is very tiny.
It's an 11 by 11 pixel image.
And so, when we stretched that,
only the center pixels
actually get stretched.
And we set that using the
button, UIButton's appearance.
We set the background image
for the normal control state.
And now, all of our buttons
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
in our application
have the same look.
Now to do tint color with
our lovely puce color,
we just set the tint
color on the window
and we could have done this
on each individual view.
But then, if we needed to make
a change which designers tend
to do every once
in a while, we--
we'd have to go make
the change globally.
In this way, we just
make one change
and then we can tell them
it took several hours
and it took seconds.
Now, I'm moving on to getting
the blur for the buttons.
Our launch view controller
is the first view controller
that comes up when the
application is launched.
And our designers
wanted the background
to be the normal color but
they wanted the buttons
to blur the content
that was behind them.
And so, when this-- when this
View Controller comes up,
it gives-- there's a
method called update in--
one of my own methods
called update interface
and if we have updated
the button,
I have another convenience
method called applyBackground
ToButtonSourceBlurFromView.
And what this does is it
takes a button and a view
that you want to blur from.
And it basically just calls
drawViewHierarchyInRect
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and makes the blur and applies
it to the button background.
And this is the bulk of the
work happens right here.
As Brandon mentioned, we have
to start an image context
with UIGraphicsBegin
ImageContextWithOptions,
and we set that to
the size of the button
because that's what
the size we need.
But we also need to know the
buttons' coordinates inside the
background views
coordinate space and we need
that because you need
to position the view
so that it draws
correctly into the context.
If you didn't actually
reposition the view, would it--
they both draw at 0,
0 inside the context.
So, what you need to
do is in this case,
we need to offset the left and
going to go offset to the--
offset upwards so that the part
of the button that's hovering
over is what actually gets
drawn into the context.
Once that's done, we
call UIGraphicsGetImage
FromCurrentImageContext
to get an image out of it
and then we end the context.
And then this is where
the blur magic happens.
We're applying a light effect.
And like Brandon mentioned,
this is going to be
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
in this sample code as well
as another sample code that's
already on the developer sight.
It's a fantastic amount of math.
It's fun to go look at
but it really doesn't--
it's not all that
interesting care.
But I encourage you to all
go look at how it's done.
But once we have that
image, that's not blurred,
we set it as our
button's background image
and that's how you
get blur in iOS 7.
>> It's looking great, Jim.
Would you like to get started on
that kind of flipbook animation
that our designers put
to the spec together for?
>> Yeah, I should
get started on that.
>> I think UIDynamics
would be the way to go.
So, let's start talking
about UIKit Dynamics.
So, how can we make realistic
motion in your application?
There's two parts of this
we'd like to talk about today.
UIKit Dynamics as well as
the new motion effects APIs.
Let's get started with Dynamics.
The UIKit Dynamic system was
introduced in iOS 7 as a system
that lets you mimic real
world physical behaviors
in your application
and we backed UIKit
with a physics engine to
help make that possible.
Now, you can do a lot of really
cool things with UIKit Dynamics.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
You can do a lot of crazy
things with UIKit Dynamics.
They best advice I'd
like to offer you
with Dynamics is
it's really effective
when you use it in moderation.
It's really easy to go overboard
with it and it's really easy,
you'll find, to have a small
value make a big change
in your app.
To help you make dynamics
possible in your app,
we've brought along a number
of really straightforward
behaviors that you can use.
So, we've introduced
concepts like gravity.
We've introduced
concepts like collisions
where things will
bounce off of each other.
We've added pushes where you
can do both instantaneous pushes
which give a shove in
the direction as well
as a continuous push that always
exerts a push in one direction.
We've added snapping behavior
where you can have things snap
to certain points
in a very nice way.
And finally, we have attachments
where things will be touched
to a point and will
kind of maintain
that distance in
that attachment.
So, what do you need to do
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to introduce dynamics
in your applications?
It's not that difficult
to get started.
The first thing you'll want to
do is create a dynamic allocator
and you give it a reference
view that you're going
to be doing your
dynamics effect in.
After that, you need to
create a number of behaviors
that define what the dynamics
engine should be doing.
In this case, we're going
to just make a simple
gravity behavior.
And you notice, we give it
an array of items that we
like that behavior to apply to.
By default, we're making
all views opt into dynamics
so you can add your views
into that list of items.
You can also by default
have items
in your collection views
animate with Dynamics.
You can also implement this
protocol on your own classes
if you'd like to make your
own very unique things
that are opting into dynamics.
Once we've created a behavior,
we can add it to our animator
to put it in the scene.
Everything that's
attached to our animators,
all those behaviors
are going to be running
and impacting your
application right away.
>> Hey, Brandon, instead
of talking about Dynamics
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
on slides anymore, how about
I just them what it looks
like on the device?
>> That'd make a lot of sense.
Go for it.
>> So, we're going
to use dynamics
in two different
places on our apps.
Obviously, the first one is
net that [inaudible] effect
which I've got it working
a little bit better.
So, let's go pick a photo that
isn't really all that good.
There is a photo of
a taxi that can go.
And then what you can see now
is as the shred line goes up,
each individual one of those
boxes gets a little bit
of a dynamic effect added to it.
We can go delete
another one to see it.
So, the animation that was
happening before is still
exactly the same.
But now, as that scanline
goes up and it hits a row,
each one of the boxes
on that row gets added
to a gravity behavior.
And then, each one of
those also gets a push
in a general random
upwards direction
of some minor amount
of magnitude.
And that gives them the effect
that they're being
popped off like that.
It looks like the line
is burning through them
and tearing them apart.
So, it's getting pretty close
to what the designers want.
They may want to iterate
on that a little bit.
But the other place
that we really wanted
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to use Dynamics was in our
flipbook in how we show photos
that we've taken during
the run to our users.
I mean, you can go through and
swipe but this thing is going
to take a picture
every three seconds.
So, you're going to swipe
through thousands of photos.
Not very interesting.
So, instead, what we're
going to do is we're going
to make a flipbook effect.
And what this is actually
doing is it's just iterating
through every photo that you
took while you were walking
around the campus.
Surprising a little code
make this happen as far
as Dynamics is concerned.
What's actually happening is
in the upper left hand corner,
we basically placed
a view on the screen
and through some CAAnimation
or view-- a UIViewAnimation,
we just set the alpha
and the transform.
And then we give a little bit
of a shove, instantaneous push
so that it will land in the
light pole in the middle.
And that light pole
is a boundary that--
it's provided by UICollision.
And then, because things on
our simulation are bouncy,
it bounces off and in the
second part of that bounce,
there is some more animation
to shrink the view down
and animate its alpha
out to zero.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now, this is all fine
and good and everything
but Dynamics really,
we want you guys
to make your applications
more immersive with Dynamics.
We don't want you just
make things jiggle
and bounce and fly around.
So, Dynamics are really
meant to be interactive.
So, while this is running,
if someone was like saying,
well that's a really cool tree,
you should be able to grab it
and pull out photos and make--
so that the user can look at it
and say, "Well, it's a
really nice minivan."
I know, geez.
There's another one.
But, you get the idea.
The simulation never stopped.
You just added new
behaviors to it.
So, while this thing is
running, you can do all sorts
of different interesting
and unique behaviors just
by changing what the
animator is doing.
So, let's go-- take a look
at what this flipbook
looks like in code.
So, we have a flipbook
View Controller
that represents what I
just showed on screen.
And in our viewDidLoad, we're
going to create an animator
and [inaudible] the
reference view
of our view controllers
content view.
And then we create a
simple gravity behavior
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and we give it a little bit more
gravity 'cause I want things
to fall quicker.
And then we create a
collision behavior,
and there's two reasons
to create this.
One, we needed that boundary
in the light pole so it--
the view or the image could
bounce off of something.
But we also need to know
when it bounced off of it.
And UICollisionBehavior
will actually tell you
that through one of
its delegate methods.
Second, we needed more
springiness in our simulation.
By default, normal thing--
everything in UIDynamics
has an elasticity of zero.
So it means it's not
really bouncy at all.
And so, to affect this, the
Dynamics, you create an instance
of UIDynamic item behavior.
And in this way, you can
actually change the properties
of any individual item or
a whole collection of items
in your simulation by changing
the properties on this behavior.
So, in this case, we set the
elasticity all the way up to one
and then we add all three
of those behaviors
directly to our animator.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Then, as we iterate through
the photos, there's a bunch
of code here that gets the
photo and places it on screen
which isn't terribly
interesting.
This is the push.
We instantiate the push
behavior with our--
with the view that
represents our image.
We make the mode instantaneous
so it doesn't continue
to push it.
And then, we just basically push
it to the left a little bit.
That is all the momentum
we're actually pushing
on to that view.
Everything else happens
from this initial push.
And finally, we add
that container,
that image to the other
behaviors that are already
in play in the animator.
Now, down here is
the delegate method
from our CollisionBehavior.
CollisionBehavior
endedContextFor
ItemWithBoundaryIdentifier.
I love our names sometimes.
This is important for us
because of two things.
One, we needed to place that
view that you guys are focusing
on so that the images don't look
like they're just bouncing
all over the place.
And two, we needed to
complete the second part
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of our animation, the
fading out of the view
and of the-- in the scale of it.
You also noticed that
in the views animation--
the view animations
completion block, we're going
and removing the item
from all the behaviors
that it was attached to before
we remove it from the superview.
And this is important to note
because while your
views can be off-screen
and still being processed
by Dynamics,
if they're not actually
imparting anything in your scene
or they're not having any kind
of effect on what the user sees,
it's in your best interest
to remove those views
and those behaviors
from the animation.
Otherwise, a view you can
imagine that's falling forever,
the system has to track
that and more tracking
of more space means more memory.
So, when a view no longer is
needed, go ahead and remove it
from the behavior
and the behaviors
from the animation
and all is good.
And one final thing I want to
point out with the grabbing
of the view, that was done
with no animation at all.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
That was all just an
attachment behavior and gravity.
So, how do we know to remove
that behavior and the view
from the screen if there's
no completion block.
Well, we're going to use another
dynamic item behavior here
and I called it off-screen
behavior,
and it's not actually
going to impart any kind
of behavioral changes
on the scene.
What it's going to do
is it's simply going
to call its action block, and
the action block is something
that we call every time
the scene is updated.
This block is a way that you
can interact with your scene
for this behavior or for any
other part of the simulation.
And so, in this case,
as the view is dropping,
we check to see
if our containers frame
has falling outside
of the windows bounds, and
when that actually happens,
we know that we're
no longer on screen
and we can actually remove
all of our container view,
the following container
view from the behavior,
from the gravity behavior.
We can move our own off-screen
behavior from the animator
and then we can remove the
container from the superview.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Pretty cool, huh?
>> That's looking really cool.
I'm really digging
the flipbook animation
that you have going on there.
>> Thanks.
>> The next thing
we'd like to talk
about is how we can
create motion effects
in your applications.
Now, one of my favorite
things that we added
in iOS 7 is the sense
of parallax
where you can see how icons
move around on the home screen,
alert views float
above other views.
It's a really cool way
that we use to show--
give users the sense of
depth in your applications
and across the entire system.
So, as a reminder, this
is what that looks like.
We have an alert view
floating above some tabs
in that really cool
new Safari tab view.
And if you pay attention
to the top and bottom
of the alert view, as the
screen tilts up and down,
you notice how you can actually
see behind the alert view.
It really gives you a sense
that it's actually a layer
that's floating above the tabs.
These are made possible
using UIMotionEffect.
This is the API that you all
can use to create effects just
like you see on the home screen
or action sheets, alert views
and so on and across
the entire system.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now you can think of these
similarly to CAAnimations.
CAAnimation takes
time as an input.
UIMotionEffects take
device motion as an input.
We've done a ton of work to
optimize these behind the scenes
to have a very minimal
impact on the user's battery.
So we would really
encourage you to take the time
to use UIMotionEffects
rather than trying
to roll your own system.
So to help you understand
how motion effects work,
you really need to
understand what the inputs are
to device motion.
So as you tilt your
phone to the right,
you're getting a
positive 1 effect.
As you tilt it to the
left, a negative 1 effect.
As you tilt it down,
you get a positive 1.
And tilting up, you get
a negative 1 effect.
Make sense?
Let's do it again
just to make sure.
So again as you tilt
right you get plus 1,
tilting left gives
you a negative value.
Tilting down gives you a plus 1.
Tilting up gives you
a negative value.
And what you're looking at there
is how your thumb is actually
hovering above the screen
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and how you actually
see different parts
of the screen behind your
thumb as you tilt the device.
To help make this easier
in your application,
we've provided
UIInterpolatingMotionEffect.
This is something that we're
providing as part of UIKit
that makes it easy to adopt the
motion effects in your apps.
It's very easy for you to use
interpolating motion effects
to interpolate between the
minimum and the maximum value
that you define when you
create the motion effect.
You know, what we apply
the animations to is
to a key path that you provide.
We can apply motion
effects to anything
that is animatable by CA.
The interpolating
motion effect is going
to automatically update
based on the device motion
as your users interact
with the screen.
And all you need to do to
make this work is attach them
to a UIView anywhere in
your-- outside your app,
and we'll start applying
motion effects to it.
It's really that simple.
If you want to do some
more advanced things,
there's a couple other bits
of API for motion effect.
The first is UIMotionEffect
group.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
You want to group every motion
effect that you want to attach
to a view into a single
motion effect group
so that we can evaluate
them simultaneously.
Now you're probably
already thinking
of these really cool ways
to take advantage
of motion effects.
And some of you are probably
thinking, "Well, that's great
but I want more than just
a simple interpolation."
Luckily we have a solution for
you, and that's the ability
to create your own
motion effects.
The method that you need
to implement is keypads
and relative values
for viewer offset.
The viewer offset
that we call you
with is what we're just
playing with with our phones,
that plus 1 to minus
1 on each axis.
You return back to
us a dictionary
with keypads and
relative values.
Those keypads are the set of
pads that you want your effects
to be applied to and the
relative values are what you
actually want that value to
be as the name would suggest.
This allows you to do a number
of incredibly cool things
with motion effects
in your applications.
So, what we want to
do with motion effects
in our app are a couple
of interesting things.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
The first thing our
designers want us
to do is apply some motion
effects to the buttons
on our home screen to give
them a sense of depth of rising
above that background view.
It's the same thing that you see
on the home screen
of your iOS devices.
They also put that lens
flare into our effect
because everyone loves
JJ Abrams lens flares.
But we thought why don't I
go a little bit beyond that
and actually make
that lens flare come
to life in our application.
So, Jim, why don't we see
what we can do with that?
>> All right.
What I came up with is not
exactly what our develop--
our designers came up with
because that's clearly shopped
and I'm not going to be
able to do that, so--
But what we came up with
I think is a lot cooler.
So, you can see that
before I pick up the device
that we have I think
reasonable effects
in [inaudible] of a lens flare.
And so when I pick up the
device that you'll notice though
as I start moving the
device in the next motion,
not only do you see the buttons
move but you actually see
that the lens flare is
actually moving along
like a diagonal line.
And you can also, it's
kind of hard to tell
but if you move really far
that the colors become much more
subdued and much more brighter.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And then if I go in the
wide axis, the buttons move
and then the color actually
also changes on as well.
So as you actually move a little
bit, it's a little distracting
with the buttons, but the
lens flare effect is actually
pretty cool.
And this is all done
through UIMotionEffect,
and let me show you
what that looks like.
We'll start off with how we get
that altitude effect
on the buttons.
Now we're going to do this
in the same exact spot
where we had a blurred
red button.
So we're in our launch
view controller.
And so what we need to do is
we need to create two instances
of an
UIInterpolatingMotionEffect,
one for the x-axis and
one for the y-axis.
So we create one with a key path
of center.x and we set its type
to UIInterpolatingMotionEffect
TypeTiltAlongHorizontalAxis.
And we give it a minimum
and maximum relative value
of negative 10 and 10.
And what that means is that
wherever center.x is normally
for that view, it won't
deviate more than 10 points
in either direction
on the x-axis.
And now, we-- and
we do the same thing
for the y-axis right below it.
It's the exact same code.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
The only thing that's changed
is the key path is now center.y
and the type is vertical access.
And because we want
these to be evaluated
at exactly the same time, we
create a motion effect group.
We add both of those
motion effects
and then we add that
to the button.
So each button has its own
grouping of motion effects.
And that's how each button
moves like it has some altitude
above the view it's below.
Now the LensFlare
is not something
that was easily just done
through interpolation.
But it wasn't terribly
difficult to get done.
So we created a view
called lens flare view.
And in its initialization
we have a thing,
a method called
addFlareToEndpoint.
And that's basically a nice way
of saying that I created a line
from the top left and I
made it go down at an angle.
And we create these
lens flare blob views
that represent each
individual blob along that line.
The next thing that we do
is we create a random color
and we create an instance
of our custom subclass
of UIMotionEvent called lens
flare color motion effect.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And it's a pretty simple class.
With the color, once
we initialized with it,
we pull out the components
that we're interested,
the hue and the brightness.
And then we implement key
paths and relative values
for viewer offset because
we map a horizontal movement
to brightness and we map our
vertical movement to the hue.
And we do some exciting
math to get a--
compute a new color value
based off the viewer offset.
We create a new color
and because our lens flare blobs
layers are actually CAShape
layers, the key path
that we need
to return is layer.fillColor
and then we just give it the
new color that we created.
And that's it, that's
how you can get the color
to actually map to
move in on your device.
Now, the motion is
even more simple.
We need the instance of lens
flare diagonal motion effect
which is also another
subclass of UIMotionEffect.
And again we implement key paths
and relative values
for viewer offset.
And again we do some more math
to basically interpolate
a value.
But what instead of looking
at both x and y, we just cared
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
about the horizontal
access-- axis, excuse me.
And what we did was we
applied our computation to it
but then we rotated that point,
and actually 45 degrees or so.
And then from that,
we are actually able
to get not only x movement
but y movement as well.
And we simply send center.x
and center.y to that rotated x
and rotated y on that view.
And then that's how that, those
views move all along that line.
It's a really neat effect and
it's important to really realize
that motion effects are more
than just moving things
around the device.
>> That's looking great, Jim.
I think motion effects are a
really cool way that we can use
to make all of our
apps come alive
within our customers' devices,
make things really feel
interesting and engaging.
>> Yeah.
>> So let's go ahead and wrap
things up from today's talk.
We've shown you a lot of really
cool stuff that you can use
in your applications to make
things look great on iOS 7.
If you want to customize
transitions in your application,
you can do that using
the new UIViewController
transitioning systems.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
You can set your applications
wide appearance using tintColor
as well as taking advantage
of the UIAppearance proxies
that we introduced in iOS 5.
Images are a great way to make
things look interesting as well,
and the new template images
are a huge win for you
in making things
look unique and get
that custom unique
tint color in your apps
across the entire
system in an easy way.
UIKit Dynamics are a great
way to make things come alive
and feel very realistic
and you can take advantage
of motion effect to really
make your apps come alive
in the user's hands while
they're using their device.
If you didn't make it to some
of these sessions earlier
in the week, I would
highly encourage you
to check out the videos.
These are all some great
talks that explain how to go
into more depth in
some of these APIs.
And if you have other questions,
there's some great documentation
online and please e-mail Jake,
he loves hearing from you
guys every single day.
Thanks for attending WWDC.
[Applause]