Transcript
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Applause ]
>> MIGUEL SANCHEZ:
Hello, everyone.
Welcome session 216, Layout
and Animation Techniques
for WatchKit.
My name is Miguel Sanchez,
I'm a WatchKit engineer.
Later you will hear from
my colleague Tom Witkin.
So the agenda for today
is to give you an overview
of the layout fundamentals
of WatchKit.
I will be going into more detail
about how to use groups to set
up your complex layouts, and
then you will hear from Tom,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
up your complex layouts, and
then you will hear from Tom,
talking to you about animation
techniques existing already
in Watch OS 1, as well
as in the new APIs
that we are introducing
in Watch OS 2.
So our target audience for
this talk is the whole range
of WatchKit developers,
people that haven't seen the
platform yet, and are learning
about the layout as well as --
as well as those of you who have
already had experience with it.
So let's start with the
layout fundamentals.
The WatchKit layout model,
I should say off the bat
is the same layout model
that we have since
WatchKit OS 1.
WatchKit and Watch OS q.
If you haven't used it yet, it's
a different model from the UIKit
and the AppKit models that you
may have had experiences with.
The difference is that in
WatchKit we are using a flow
based layout and what
I mean by that is,
you've probably seen
this animation before,
in Interface Builder,
you have your library of,
and your catalog
of WatchKit objects
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and your catalog
of WatchKit objects
and you are dragging them
on to your controller.
As you are dragging
them, they are falling
on the next available
slot on the flow.
And that flow is
initially vertical.
So here you have
a second element.
It falls on its set
slot, and, of course,
you can add a horizontal flow if
you introduce a grouping object
and tell it to use
horizontal layout.
So some important
points as a programmer
of WatchKit applications is
that you are not writing
object creation code.
All of your UI creation is
happening in story boards
and Interface Builder.
We are not providing APIsor
allocating your typical
WatchKit objects.
This does not mean that you
don't have fine-tune control
of your layout hierarchies
and alignment and sizing,
as well as animation,
as you will see here.
So we'll go into each
one of these in detail.
Let's start out with
alignment and sizing.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
All of your instances
of WatchKit objects are
subclasses of WKInterfaceObject.
All of these have properties
for setting the alignment,
and the sizing heuristics.
So alignment, we are referring
to the alignment inside
the containing object.
This is the horizontal
and the vertical alignment
and it can either be
left, center or right.
For sizing, you are telling us
what rules you want us to use
when sizing your objects both
width-wise and height-wise
and this is either fixed,
relative or sized to fit.
In Watch OS 2, these -- these
properties have been available
in Interface Builder since
Watch OS 1, but in Watch OS 2,
we are exposing more
of these through APIs.
We want to give you more
control in your code but also
to animate them as
you'll see later.
This is a new API set horizontal
and vertical alignment
with new enum types.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and vertical alignment
with new enum types.
This does what you expect.
Here you have the world premier
of WK blue box doing a
left top alignment, center,
center, and right bottom.
On the sizing API side,
we already had said
width and said height.
For washWatch OS 2, we are
exposing the relative width
and the sizing to fit APIs.
Again, it gives you more
control in your code.
Graphically this looks
like the following:
so here's a fixed
width and height
of our blue square, once again.
If you have been using this
in the previous release,
you should know that
we interpret the value
of zero differently.
In Watch OS 1, if you give us
a zero in code, we revert it
to the storyboard
value, in Watch OS 2,
we are interpreting the zero
as an absolute zero value.
So just keep that in mind.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Let's say that you want to
size the rectangle to be 75%
of the width of the
containing element.
So you can use said relative
width, with a .75 value
and you get three-fourths
of the width.
And you can do the same for
the height, if you want it
to be half of the height
of your containing element.
The second parameter in these
APIs is an adjustment value,
which can be positive or
negative, and it's applied
after you do the initial sizing.
So in this case, I will
be adding 30 to the width
and subtracting 30 to the
height and I get the following.
And finally, the
sizing to fit and sizing
to height does what
you probably expect.
You know, depending on the
content inside your rectangle,
we are sizing appropriately.
Now, let's move on
to group elements.
This is where you really start
to fine tune your layout.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
This is where you really start
to fine tune your layout.
WKInterfaceGroup, think of
it initially as a container
without default content.
It can have content as
I will illustrate later
but initially it's
just a container.
It's a tool for arranging
all of your elements.
This is where you get the chance
to pick whether you want a
vertical or horizontal layout.
This is also where you
start to introduce nesting.
And this is where you are
tweaking the alignment
and the sizing that
we just saw before
on the containing elements.
So as we saw in the first set
of slides, now I'm abstracting
to the blue shapes, you
are laying your interface
in Interface Builder and you
have the vertical layout.
You introduce a group and you
tell it in Interface Builder
that you want the horizontal
layout and you start laying
out your objects there.
So once you have defined
your containment hierarchy,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
you are able to define
things like insets
and spacings within your group.
So you can define
the left inset here.
These are point values.
Left inset, bottom inset, top
inset, right inset and right,
as well as the spacing that
is used to put aside --
to separate each one
of your elements.
Now, don't forget that your top
level container object is also
-- is also a group.
So you can set the
insets at that level,
as well as the spacing.
So we use the same spacing
for the number of elements
that you have inside
of your group.
So here you have a
spacing of 10 that is used
for the three top level
elements in your group.
Now, once you apply -- once
you start using nesting,
you are able to achieve
your complex layouts.
Here's a very simple example.
If you want the two squares
stacked on top of each other,
followed by two squares
right next to each other,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
you first use a group
with a vertical layout.
Then you use another group
with a horizontal layout
and you wrap those
two in another group
because that's the way you
achieve the horizontal layout
of those two elements.
And by default, there's
no content in your groups.
So they are transparent and
you only see your squares.
Now, let's make this more
concrete with an example
that I will be introducing
in this part of the session
and then Tom will
start animating.
So we have WKRecipes.
This is a very simple
recipe viewer.
It lists your recipes.
Fish tacos, pizza,
barbecue wings.
You can see the list of
ingredients for each one
of your recipes, and you can
see the number of servings
for each one of the recipes.
And there are other
screens which Tom will talk
about in the context
of animation.
For here, we are focusing
on the static layout
of these three elements.
So how do we do this?
The first screen that we
see is a table of recipes.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
The first screen that we
see is a table of recipes.
So in WatchKit, you have a table
controller that you can use
to layout your rows, but
it's your responsibility
to tell us what each
row looks like.
What is the structure of that?
So here we want an
image and a label.
So we have a horizontal layout,
that should automatically
tell you that that's a group
with a horizontal layout.
Then you have defined your
containment hierarchy,
and now you are going
to define your spacings.
So you have your left inset,
your bottom, top,
and the spacing.
And your alignment.
Right? Your image is
aligned center, vertically,
but it's aligned to the left in
the next slot that it falls on.
And the label also has
a vertical alignment
but left aligned.
Notice that it's left aligned in
the slot that it corresponds to,
right, because there's an image
before it, so right next to it.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
right, because there's an image
before it, so right next to it.
Sizing our images are square.
Resources.
So we have a fixed size
of 30 points on each side.
And the label, obviously
sizes to fit.
So table row layouts show us
that we can use the groups
for horizontal sizing, and then
we can fine tune our alignments,
and set some spacing.
Now, let's move on to the
ingredients controller.
Some of you might be
noticing that five hot sauce,
whatever units that is, is
probably too much hot sauce
for any taco recipe, but that's
the wrong thing to focus on.
You actually want to notice
that although we have our
table layout, we have rows,
we now have the circle element.
How do we achieve this?
The horizontal layout
is the same.
We still have a group.
We have the label, obviously,
but what is that red
circle on the top left?
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
but what is that red
circle on the top left?
We can nest groups,
as I said before.
So we are using a group here.
And here we are now
moving into the area
where groups do have
backgrounds.
They don't have default content,
but they can have backgrounds.
The backgrounds can be
either colors or images.
So we can select the
image of this group,
as well as the radius that is
used to draw the background.
And so we are setting a group
with a colored background,
blue in the schematic, red in
the real example with a radius
of 8 and then you get
the nice blue circle.
Once you have a group, you
can nest the label inside it
and it's centered in the group.
Now you have the horizontal
and the vertical centering
so this is where you start to
see the building of concepts
that we have been talking about.
And yet again, sorry
to be repetitive,
but this is the model.
Now you define -- you
find tune your left inset,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now you define -- you
find tune your left inset,
top, bottom, and spacing.
So remember, for nested
groups, you can use nesting
to achieve complex layouts,
as well as using backgrounds
within your groups whether
that's a color, or an image.
Lastly, we have the
servings controller,
which it highlights
the number --
it's a circle that highlights
the number of servings,
four in this example, for
your particular recipe.
So some of you might
be thinking,
this is a circular layout.
How does this --
how is this achieved
in the grid-like flow layout
that you have been
talking about so far?
So we have a circle of 12 --
well, a circular pattern of 12
objects, but if we look at them
in detail, these are actually
just three top level groups.
So we have the first group,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
the second group,
and the third group.
Inside of those groups, we
subsequently use more nesting.
So let's focus on
the middle group.
Sorry, let me talk about the --
at the top level groups we do
have alignment of the groups.
For example, the top group
is horizontally aligned
in the center and fixed size.
The middle one is
sized to fit --
to take up the whole
width of the container.
So now the second group has
more groups inside of it, right?
So we have a group
with vertical layout.
Then we have a group
with horizontal layout
and finally we have a third
group with horizontal --
with another vertical layout.
And if we look at
each one of those,
those themselves are made
up of more subgroups.
Once we have this
level of definition,
we can indicate the
alignment, the precise alignment
on each one of those circles.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
on each one of those circles.
Now you can clearly see
that that circle is horizontally
aligned to the right
and vertically on the top.
Then you have the left
alignment and the center
for this particular circle.
And right bottom for
the other, right?
So you have seen how the
grid-like flow layout really
gives you a lot of
power in terms
of the things you can achieve
and that's the same pattern
that we follow for the whole
-- for the whole circle here.
So group nesting is your key
to achieving complex layouts.
Now that I have given you all of
this rope, I need to warn you,
don't hang yourself with it.
It is possible to
abuse groups, right?
You have to keep that in mind.
You can go overboard by
trying to nest everything.
So some things to keep in mind.
I can't give you
an exact number.
It depends on what
your backgrounds are
or how your layout is behaving,
but keep these things in mind.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
or how your layout is behaving,
but keep these things in mind.
At the beginning of
the presentation,
I said that we are
not offering you APIs
for direct element
creation, or destruction.
This is all done
in the storyboards
and Interface Builder.
So anything you create
in Interface Builder
is instantiated.
It's created.
When you're instantiating
one of your controllers,
you're instantiating all of
the elements inside of it.
It's possible to
hide some of them.
That's one of the properties
that you have for some
of the elements, but even
though they are hidden,
you are still -- we are
still creating them.
So you might -- you are
still taking the hit
of the creation costs.
You might save on
the layout costs
because we are not
doing the layout,
but the creation
is still happening.
So keep this in mind as you
start adding a bunch of objects
into your controllers, right?
Keep them -- in mind that those
are all being created even
if they are not visible
at that particular time.
And finally, as I showed you
with groups and their ability
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And finally, as I showed you
with groups and their ability
to have images, keep in mind
that images have a transfer cost
over into your Apple Watch.
In Watch OS 1 apps, the
extension was running
on the phone, and
they have to get --
we have to get those images
over into your watch, right?
Each time your user is
using your interface.
So keep that in mind.
We have APIs for image
caching which we kind of --
you tell us to move a
certain set of images
but they still have to get
over the air to your watch.
In Watch OS 2, this
is less relevant
because the extension is
running on your watch,
but you still have
to install the app.
So you still have
a set of resources
that you are installing.
So there is still a
transfer cost for your users
from an installation
point of view.
So always remember
to use appropriate
sizes for your images.
If you give us an
image, we will resize it
for whatever you tell us
to display on the screen.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
for whatever you tell us
to display on the screen.
But by doing, that you are
adding more processing cycles
from our -- from the WatchKit
side on the watch, right?
So you have the ability to
resize your images properly,
either on the phone or in
your servers, if they happen
to be dynamic images and
this makes an impact,
in terms of the rendering
of your UI.
Finally, you will have
some images that need
to be resized, for
example, buttons.
You can use -- you don't
need multiple sizes.
You can use image slicing.
This is a UI that you have
in your asset catalogs
and Interface Builder,
you can slice your images
and tell us how they
are resizing
and we do the right thing.
So you can give us one
particular image set
and we will -- it
will be applicable
for different sizes in your UI.
So this is the end of the static
part of the talk and now I would
like to invite Tom up to
add more dynamic aspects
to this model.
[ Applause ]
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Applause ]
>> TOM WITKIN: Awesome.
Hello. I'm Tom, I
also work on WatchKit.
We will be discussing
animations and introducing those
into both your existing and
your new Watch OS 2 apps.
We will start off with
some existing types
of animation available
in Watch OS 1.
So tables are really flexible.
In certain updates on
tables will already animate.
If you insert rows,
if you remove rows
or if you update the
content within a row,
they will actually animate and
we will talk about all of these.
So all of our examples
are going to be
within the context
of our recipe app.
So let's start on
the recipe list.
And it would be great if
we could provide a way
to sort the list, either -- so
by ranking that we have assigned
or maybe alphabetical.
It's not extremely clear
how the list is being sorted
as we are doing this.
And so it would be great if
we could possibly insert a row
and say how the list is
sorted and then after a couple
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and say how the list is
sorted and then after a couple
of seconds, take
it out of the UI.
So how are we doing this?
It's really simple.
We have a table.
And we are calling
insert rows and indexes
and we are inserting
a row of status type.
And then we are getting the row
controller and updating the text
on that row and then we
are scheduling a timer
for a few seconds
to remove the row
and that method is
then implemented here.
And so inserting and removing
rows can really add flexibility
into your interfaces.
And one thing to point
out is you can insert
or remove rows of any type.
So for example, here we
have a list of recipes,
all the same type of cell,
however we are inserting a row
of an entirely different type.
So, again, it allows you to
have extremely dynamic content.
So within your interfaces.
I will also point out that if
you want to update your tables
and not animate we have 2 API
that I'm sure you all know
if you've used WatchKit
or Watch OS 1.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So moving on to the content
within a row and we will tap
into our detailed
view of our recipe.
And we have a description.
And because of the size of
Apple Watch, and the length
of a description, we
probably don't want
to have the full description
there all the time.
And so we have implemented our
description within a table row
and we show a truncated version.
It would be great if you tap on
the row, it will expand in place
and give the full description.
And so it's really nice --
it's a nice animation and it --
it provides you -- and so
the information you want,
exactly when you want it.
So how are we achieving this?
I will go back to
our blue boxes.
So we have our table cell.
And within the cell,
we have a few labels.
So we have our short label,
which has a description
with the truncated text.
We have another label,
which says tap to show more.
And then also we actually
have a third label.
So that's a full
descriptionlabel.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So the initial state of our cell
has the full description label
hidden and all we are doing
is the user taps on the cell,
is we are reversing this.
So we will unhide the
full description label
and we will hide the other
ones and just this will allow
that animation to happen,
that we handle in WatchKit.
So it's really simple.
And, again, here's the code.
So just in a few lines of code
-- within your application,
and it's a really
great experience.
And so, again, rows reload,
whenever their content
changes in height.
So if you are reloading a
row but it doesn't change
in height, there's no animation.
And so in order to achieve this,
make sure your rows have a size
to fit height, because if
they have a fixed height,
again the row isn't
actually changing.
So now we will go back
to our recipe list
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So now we will go back
to our recipe list
and visit a different
type of animation.
And back to our cell and I will
call out these arrows here.
It would be great
if, as its displayed,
we could add a flourish
of some type
so the arrows spin
around, for example.
We can accomplish this
with an animated image.
So animated images are really
powerful, and they allow you
to cycle through a series of
images over a given duration.
And they also allow you to
repeat and reverse animations.
And it's the only
type of animation
within WatchKit that
will allow that.
So, again, there
are very powerful.
I do want to point out,
though, if you do have a series
of images -- so the number
of images can quickly add up
and so their costs in terms
of load times and performance,
as well as -- and
so memory usage.
Keep that in mind and reduce
the number of images as far
as you can, and the size of the
-- and the size of the images
and you will get
better performance.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I also want to point out
now our new picker object,
in Watch OS 2, and it allows
you to scrub through the images
within an animated image
so with a Digital Crown.
It's really powerful and
it's a great experience.
If you would like more
information, there is a session,
it's WatchKit In-Depth
Part 2, it's to learn
about the new picker object.
So that's existing
functionality in WatchKit.
I know a lot of people are
interested in the new stuff,
and so the animation API that we
are introducing in Watch OS 2.
So the animation API allows to
you animate certain properties
on your interface objects,
including the opacity, the width
and the height, the
alignment, so left to right
or top and bottom or center.
The background colors on
groups, so the color or the tint
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
The background colors on
groups, so the color or the tint
on an image like we have here on
the slide and the group insets.
So a lot of stuff
that you can animate.
If you have used -- if you
have programmed on iOS,
the API may look familiar.
It takes a duration
and an animation block
and all the updates you perform
within the animation
block will be animated
to the given duration.
So we will just jump right in
and talk about some examples
and hopefully show
some techniques,
as well as how you can integrate
this into your WatchKit apps.
And so our first example will
go back to our detailed view
in the app and tap into
the serving screen.
And we are going to add an
animation of where the circles
around the ring will
fade in sequentially.
So like this.
So in code, we are going
to loop through our groups
around that outer ring.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
around that outer ring.
So every circle is a group.
We will create a dispatch block
and schedule our animation.
And then within the block,
we will animate the alpha
of the group, and
it will fade in.
So it's a very simple,
but you get a cool effect.
I also want to point out, we
are introducing two new API.
So did appear and will
disappear and they are
on WKInterfaceController.
These are important for your
animation and I will talk
about that in a moment,
I'll also point
out that this is
coming in a future seed.
So in this interface, use
did appear not will activate
if you are beginning
an animation
on the appearance of a view.
I know a lot of people are
using will activate right now
to start an animation, so will
activate is probably called
prior to it appearing on the
screen so it's not a good place
to start your animation.
So use the did appear method.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So use the did appear method.
Also you can stagger your
animations with timers or GCD.
If you do this, keep in mind,
that you can only update a
controller if it's active and so
if you are animating after the
controller has deactivated.
So those updates won't
actually be applied and so keep
that in mind and make sure
your controller is active.
Also keep track of the total
duration of your animation.
If you are chaining
a lot of animations,
the duration can quickly add up,
and most likely the user is
only interacting with your app
for a few seconds and if you
have a multisecond animation,
it's just prolonging your
times within your apps.
So be mindful of that.
And also just for convenience,
you can set your initial values
within the storyboard.
So for example, in this
interface, all of the --
so all the circles are initially
hidden and have an alpha zero
at the start and we can
have that in the storyboard
and not have to worry
about it at runtime.
So we will move on to
our second example,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So we will move on to
our second example,
which is our ingredients screen.
And it would be nice if we
could have the labels fly in.
So as you can see here.
So we'll break out
to our blue boxes.
And so we have our table row.
And as we showed earlier, we
have our number background
on the left which is the group
and we have our label
on the right.
And now we are going to add a
new group in between the two
and we will call
it a spacer group.
And groups are really
powerful in terms of laying
out the content within them
but they can also affect
the content around them.
So because the content --
and so because our layout
in WatchKit is flow based,
a group within the flow
can affect the other ones.
So, for example, here,
our initial state
of the cell has the spacer group
to be a full width and what
that does is it actually
pushes the label off the side
of the screen, and so you
can use this within --
so within your apps,
both for horizontal flow
and vertical flow
to kind of affect
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and vertical flow
to kind of affect
where things are laying out.
And then as we animate, all we
are doing is updating the width
of our spacer group and that
label then will come in,
because we are recalculating
how our flow is laying
out the interface.
So in code, we are looping
through all of our table rows
and we are fading in both our
number background and label,
as well as setting the
width on that spacer group
and we are wrapping all of this
within in a single
animation block.
If you can, you can improve
your performance by wrapping all
of your animations within
a single block, however,
as I just -- as I showed,
if you are doing a sequential
animation that's fine,
but just keep in mind that
having a lot of animations
at once can affect
the performance.
So invisible spacer
groups are really powerful
and you can adjust the width,
height or alignment of them
and affect your layout.
And one thing to point out is as
you animate, we actually relay
out your entire interface and
this is how I can set the width
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
out your entire interface and
this is how I can set the width
on that group and the label is
actually changing its position,
even though I'm not -- and so
I'm not changing it myself.
And so now on to
our third example,
which is the most
complex of the examples.
So we have this screen where
you can add a note, and we'll --
and if you tap on add note,
we will have our default
on text input on the system.
If you choose an
option, we'll insert --
or we'll animate
in a speech bubble.
And so already we have
a more complex animation
but we're going to go
one step further on this.
And if you tap confirm,
we will animate
in a confirmation screen.
So all of this is
within one interface
and it's all using
the new animation API.
And so we will break
this up into two parts.
Let's talk about the
speech bubble first.
So back to a wire frame.
Within our interface,
we have a group
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Within our interface,
we have a group
and that's the text
container I will call it.
Within that, we have our
text bubble which is on top,
which has our label in it.
And then below that, we have
our confirmation button.
As we animate, our initial
state has our text, so bottom
and right aligned,
as you can see here,
the button is faded out.
As we animate, we will update
the width of our text bubble
and the height and
fade both that
and the button in,
as you can see here.
And so we get that effect --
and so we get that effect
with just a few lines of code.
On the text bubble, we
were updating the width,
the height and alpha as I said.
And the size to fit
height is because we want
to fit the full text
of that label.
Regardless of how long
that note is, it will fit.
We will fade in the button
by updating the alpha
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and we'll update the
height of the text container
as well to fit everything.
And wrapping all of that
within an animation block.
So that's part one
of that animation.
Part two is where we show
the confirmation screen.
And so back to our blue boxes.
Here we have our text container
and I won't include the objects
within that here
just for clarity.
But also within the interface
below, we have another group,
which I will call the
confirmation container.
And so what we are doing here
is we are wrapping the different
parts of our interfaces
in their own groups,
and what that allows
us is we can --
we can collapse or expand them
to show different
parts of the interface.
For example, here is the
initial state of that interface.
So the text container
is full height
and the confirmation container
actually has a height of zero
and so it's hidden on screen.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and so it's hidden on screen.
And because of how our new
behavior in the set width
and set height API, you can
actually achieve a higher width
-than zero.
As we animate, all we're
doing is reversing the heights
of these.
So the text container
now has a height of zero
and the confirmation
container now is a full height
of the screen.
In code, it's exactly what I
said, we are updating the height
of the text container,
the height of the confirmation
container and just wrapping
that within an animation block.
And so that's how you get
the effect of one part
of the interface sort
of zooming off screen
and the other zooming on.
And so I want to bring out a few
notes on animation, just to kind
of wrap up and summarize
but also just to point
out a few gotchas that
you might run into.
So any update that
affects the sizing
of your interface
objects can actually --
can actually animate the layout.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
can actually animate the layout.
So, for example, if you
update the text of a label,
that is sized to fit, that label
is changing in width or height
and so if you do that
within an animation block,
it will actually animate to
the new frame of that label.
However, you won't actually
be animating the application
of the text, but just
the sizing of that label.
If you have lots of
animations at once
or if you have a complex type
of layout within your interface,
that can affect the performance,
and so definitely keep
that in mind, and absolutely
make sure to test on hardware.
So the simulator is a great
way to build up your animations
and to make sure
everything is working,
but for actual performance
and to see how things
will actually work,
make sure to test on hardware.
That's extremely important.
And also a thing to point out is
that this animation
is functional
within your applications.
However, if you call it within
a glance or notification.
So those updates
will still be applied
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So those updates
will still be applied
but they won't be animated.
And so there's no
point in using this
within a glance or
a notification.
A few more notes.
So use with restraint.
And that's because animation,
it should never be the
focus of your interface.
If the animation is the reason
that your interface exists,
it probably is time
to rethink that.
And also, again, keep
the total duration short.
We -- so the amount of time
within your app is probably
on the order of seconds and so
don't prolong the animation,
like, any more than you have to.
And there's a great
session on this,
"Designing with Animation",
I highly recommend that.
And so to wrap up and conclude
the talk, and so layout
in WatchKit is different
than UIKit and AppKitt
where it's specified
in design time
but very flexible at runtime.
We have a lot of API and we're
introducing a lot of new API
that allows you to update, to
update your UI at one time.
Again, it's flow based
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Again, it's flow based
and so you are specifying
the layout heuristics
of your objects but WatchKit
itself is doing all the layout.
And groups are really powerful.
And as you have seen, you can
build very complex interfaces
that you may not have thought
were possible within WatchKit.
And now to add animation
within your apps.
So animation is a great way
to add liveliness or feedback
within your apps, I'm
sure you all know that.
We have lots of ways
already within WatchKit
that you can introduce these
animations and we are making
that even more powerful
in Watch OS 2.
So for more information,
there's a lot of documentation
and technical support, we will
also be releasing our sample
code as a project on
developer.Apple.com.
And for general questions
we have our evangelist,
Jake Barrens.
So ask him all the
questions you may have.
There's tons of related
content this week
and some are still happening.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and some are still happening.
I want to point out the Tips
and Tricks one tomorrow morning,
and the Design Tips and
Tricks one tomorrow afternoon.
So both are very good.
So thank you.
Enjoy your time here.
Thanks.
[ Applause ]