Implementing Engaging UI on iOS

Session 226 WWDC 2013

Users expect interesting animations and responsive interactions. Learn how to achieve this by making view controller transitions smooth, optimizing performance when using images, and harnessing customization APIs alongside new iOS 7 features.

[ 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.


So, here's what our designers have put together for us.

We can have the ability to view photos in our application 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.


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.


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.

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 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.

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 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 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.

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.

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 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.

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 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, 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.


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 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, 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.

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, 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 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 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, 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, 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.

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.

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 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 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 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.

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 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 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 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.

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 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.

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 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.

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.

Pretty cool, huh?

That's looking really cool.

I'm really digging the flipbook animation that you have going on there.


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.

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 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.

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.

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.

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.

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.

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 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.


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.

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.


Apple, Inc. AAPL
1 Infinite Loop Cupertino CA 95014 US