WWDC2017 Session 412

Transcript

[ Cheering ]
[ Applause ]
>> Good morning and welcome to
Auto Layout techniques in
Interface Builder.
I'm Jonathon Mah.
I'm an engineer on the Interface
Builder team, and I'll be joined
onstage shortly by my colleague
Jason Yao.
In this session, we'll be
starting with a partly built iOS
app and use that to demonstrate
a series of layout and
interaction techniques.
Now it seems like every few
months there's a new app to help
people find dates, and this is
another one of those months.
So this is the app we're
starting with.
[ Laughter ]
[ Applause ]
Like other dating apps using
Auto Layout is about building
relationships, relationships
between views.
And building relationships does
take work.
But it's the kind of work that's
rewarding because having laid
out our interface using
constraints, our app can scale
across a variety of screen sizes
and adaptations, including ones
which might not exist yet.
Now, if you've never used Auto
Layout before, there's some
great resources online and past
sessions from WWDCs.
But today we've got a lot of
content to get through, so we're
not going to cover the basics.
In fact, we have six techniques
that we'll be walking through.
You can use these in your own
apps, either as is or combine
them together to form a larger
effect.
And with that, let's just jump
right into the first one, which
is changing layout at runtime.
Now at the top of our app we
have a slider area where the
user can set a distance.
And usually, we expect the user
to set this once and then not
need to change it for a while.
So we'd like for this area to be
able to collapse away and reduce
clutter in our interface.
Now, if we think about this from
a layout perspective, what we're
trying to do is collapse the
height of this area to 0.
So, if we add a height
constraint and then set the
constant to 0.
If we did this in Interface
Builder, we'd get something like
this.
So what we're seeing here is our
layout with a bunch of red lines
indicating that our layout
doesn't have a solution.
We have what's called a
conflict.
So a conflict means that we've
asked the layout engine to do
multiple incompatible things.
In this case, set the height of
this area to 0 while also
keeping the height large enough
to fit the content inside of it.
The technique that we'll use to
solve this is to take the view
that contains our control, our
slider, and our labels, and
we'll wrap it in another view,
here indicated in orange.
Now instead of just collapsing
the view containing our
controls, we'll collapse this
outer view.
The inner view maintains its
full height and satisfies all
its constraints.
But the outer view clips the
inner view because clips
ToBounds is enabled.
And this gets the effect of
hiding the interface elements.
Let's see how this looks in
Xcode.
So we have the slider area
designed in Interface Builder
right here, and we're designing
it in the expanded state, so we
can work with it more easily.
So since it's expanded in
Interface Builder, we'll be
collapsing it at runtime.
So we'll create a constraint at
runtime to set this, the outer
wrapping view height to 0.
And then, at some point, in
response to the user touching
the button, we'll activate that
constraint.
Now if that were the only thing
we did we'd still hit the
conflict situation that we saw
before, so we'll deactivate a
different constraint, the bottom
edge of the control container to
the wrapping view.
So this will allow the outer
view to collapse.
Let's look at the full code for
this.
This is in our view controller
subclass and so we have three
properties.
Two of them are outlets to both
that wrapping view and the lower
constraint, and we have a
property to store our 0 height
constraint.
In response to touching the
button, the first thing we'll do
is ensure that the 0 height
constraint is created, if we
haven't made it already.
And then because we want the
behavior to toggle between shown
and hidden, we'll figure out
which direction we're going.
With that done, we'll then
deactivate and activate the
constraint that we want to have
-- that we want to get our
interface into the final state.
Now, if you notice carefully,
we're deactivating one
constraint before activating
another constraint.
We're not simply toggling both.
And the reason for that is that
Auto Layout tries to help us
avoid the conflict situation.
Because, as soon as we get into
a conflict, it'll log a message
to the console saying hey, I've
detected that these constraints
are conflicting with each other.
So if we activated, for example,
0 height while the bottom
constraint was still activated,
we'd get that message.
By deactivating first, we avoid
that.
So this is what we need to get
our interface in the final
state, but we also would like to
animate the results so that the
user can see -- maintain some
context in the application as
the transition happens.
So to do that we'll use a UIView
animation block, and we'll wrap
a call to layout if needed.
So this evaluates the
constraints, gets frame values
and applies to them to a view,
and then UIView animation will
capture that and animate the
result.
So we're deactivating the bottom
constraint and that gives us
this animation effect.
This isn't quite the effect that
I want, but I can change that
simply by keeping the code
exactly the same and changing
which constraint our edge
constraint outlet is connected
to.
If I had said connected to the
top constraint, then the
animation changes and it gets
the effect that actually I think
I prefer.
So we just saw an example of
changing the layout in our app
by changing the constraints.
Now let's look at another way to
change the layout, and we'll use
that to track touch.
So we have this central card
area in our app, and we'd like
it to follow a touch around the
screen and add a little rotation
as you get close to the edge and
snap back once you let it go.
So the view's position onscreen
is generally defined by its
frame and when we're using
constraints and have constraints
to this view, the layout engine
owns the value of this frame.
So the value itself is computed
from the constraints.
But there's another property
that affects the view's position
onscreen and that is the
transform, and this applies an
offset from the frame.
So the type of this is a
CGAffineTransform.
And this lets us add a
translation, a rotation, and a
scale that gets applied after
the frame has been computed from
constraints.
So we can use this to get the
effect that we're after, and
I'll jump over to a demo and
show you how it's done.
Okay. So here is our app in
Interface Builder.
And we'd like to make the
central card area move around
with the touch.
Now I've just added a gesture
recognizer, a pan gesture
recognizer, from the object
library to this area.
And when I add a gesture
recognizer, it appears at the
top level of the scene, so
[inaudible] and in the outline
view.
I'll open the assistant editor,
so we can see our view
controller code.
And I'll control drag from that
pan gesture recognizer to a spot
in our source code.
And this will let me add an
outlet.
Or, in this case, I want to
connect an action, and I'll call
it panCard.
I'll switch the type from any to
pan gesture recognizer.
This is the type of the
parameter.
And specifying pan gesture
recognizer let's me use
properties of that gesture
recognizer within the action
method.
All right.
So we have our method stub here.
And I also have an outlet that's
connected to that card view,
which is what we want to move.
So, in this method, I'm first
going to ask the sender, which
is the gesture recognizer, for
its translation.
In effect, how far the user has
panned or dragged.
And then I'm going to use the
result to apply a transform to
this card view.
Now the transform's computed by
this helper method right here,
which generates both a
translation and adds a little
rotation, depending on the
exposition of the card.
So I'm going to hit build and
run, and we'll see how this
looks.
All right.
And so we have our app.
And now, if I touch and move, we
get a rotation, and it will
follow the touch.
And then if I let go, now the
card just stays where it is,
because we're never resetting
the transform.
It's just staying the last value
that we gave it.
If I touch and move again, we'll
see that it will snap back to
the original position.
That's because the transform
isn't offset from that.
So, as soon as we go back with a
new translation, we're going to
be relative to the original
frame.
So we'd like the card to return
back to the center once we're
done with it.
Once we let go of the touch.
Now we can do that by looking at
the state of the gesture
recognizer.
So we have the same code here.
And then, when the state is
ended, we'll reset the transform
back to the identity transform.
Let's build and run again.
So now when we release the card
snaps back.
So, of course, we'd like to
animate that snapping back, so
let's just do that.
So we have the same reset to
identity code.
And I'm using the UIView animate
variant with the spring options.
So this will give us a different
effect.
So I'll build and run again.
So now, if I release the card,
it will bounce back to the
original position, and I kind of
like this playful behavior.
[ Applause ]
Thanks. Yeah, I think people are
going to show their friends
this.
So I think we're in a good spot.
All right.
So we just saw that the view
position is a combination of
multiple properties.
Not only the frame, which is
derived from the constraints,
but we can also use the
transform to affect where the
view is onscreen.
And that was just a couple lines
of code to add this fun
interaction.
So I hope that you guys will
play around with that in your
own apps, because it's a lot of
fun.
So transform is great for
temporary changes, like we saw.
Like tracking a touch or an
animation between states in your
interface.
And then we reset back to the
identity transform when we're
done.
So now that we have our app
acting playfully, let's talk
about making the text look
great.
To do that, we'll support
dynamic type.
Dynamic type is a technology on
iOS that provides both a set of
text styles.
For example, headline, body,
caption.
And user control over the size
of those styles.
Here's a few example apps, and
this is with a default text size
set.
Now, if the user preferred a
larger text size, for example,
we'd see messages adjust.
So the text increases, and then
all the graphic around -- the
bubbles around the messages
increase.
Also the input field gets
larger.
Similarly, with calendar, an
event layer.
And our app looks like this.
Yeah, nothing changed.
Or, depending on how we created
our app, it might look like
this.
Where some text increases but
our layout is not right, and its
unreadable.
Fortunately, Interface Builder
makes it easy to fix this up for
us.
So let's take a look at how to
do that right now.
All right.
Back to our app, and let's take
a look at making these two
labels respect the system font
size.
Some I'm going to select this
lower label here.
And over in the inspector, I'll
check the automatically adjust
font checkbox.
Now, if you've got a keen eye,
you'll notice as soon as I did
that, I had this little warning
icon pop up.
And this reminds us that for
this property to take effect, we
need to specify a text style for
the label.
So right now the font for this
label is a fixed value of system
12.
And I'll change it to a text
style by opening the inspector
and selecting an appropriate
style.
In this case, I'll choose
caption one.
So this happened to correspond
to system 12 at the default text
style, so our canvas looks the
same.
I'll do the same with the upper
label.
This already had a text style
set.
And I'll build and run again.
Okay. So this comes up and it
looks the same because we
haven't changed the text size
yet.
Now we can change the text size
by using the settings app on the
simulator, but it's a little
cumbersome to switch back and
forth between settings and our
app.
So I want to show you another
way to do that.
If I jump back to Xcode, I can
use the application menu to open
develop a tool accessibility
inspector.
So, from here, I can choose to
target the simulator.
And on the settings tab I get
this font size slider.
So I'll pull up the simulator
side by side, and now I can
change this slider and see our
app react in real time.
This makes it a lot easier to
test dynamic type changes.
[ Applause ]
By the way, if I had an iPhone
plugged in or set up for
development here, I can also
choose to target that connected
phone.
So we see our app adjusting --
reacting to the font size, but
if it gets too large then our
labels are running into each
other and overlapping.
So let's go fix that.
So, in Interface Builder,
whoops, I'm going to jump back
here.
I want to get that out the way.
The text area, down here, the
size of that is defined by a
fixed height constraint
[inaudible] constant over here.
Now, instead, we'd like this
size to vary depending on the
size of the labels within it.
So we have the bottom label
constrained to the bottom and
the top constrained to the top.
So, if we added a vertical
constraint between the two,
there'd be enough information to
size this area from the
constraints of the labels and
the size of the labels
themselves.
So let's do that.
I'll control drag from label to
another.
And I can choose to add a
vertical spacing constraint, so
this will keep the labels
separated by the same distance
they are in the canvas right
now.
I can choose to add a vertical
baseline standard spacing.
So this is similar to vertical
spacing except UIKit will adjust
the constant of this constraint,
depending on the text style and
the current font sizes of the
labels involved.
So I'll choose to add one of
those.
And now I can select and remove
the fixed type constraint and
then build and run again.
So now things are looking a lot
better.
Our content area is adjusting
for larger sizes and also
shrinking down for smaller
sizes, if people want larger
information density on their
displays.
So, using two properties in the
label inspector, both the font
and the dynamic type property,
we can make our labels adjust
dynamically as the font size
changes.
And we saw using accessibility
inspector to test different
sizes.
There's a talk later this
afternoon, Building Apps With
Dynamic Type, with a lot more
information, and after this
session, if you want to try out
how your own apps looks, if you
change the font size, you can
also get to the setting directly
on your phone.
If you go through accessibility,
you get the larger accessibility
sizes' option, which gives a
large range of values for the
type to vary on.
So check that out.
Now it's time to add some more
views to our app.
And I'd like to bring up Jason
to introduce you to this safe
area.
Jason.
[ Applause ]
>> Hello, everyone.
My name's Jason Yao.
I'm an Interface Builder
engineer, and it's a pleasure to
be with you here today.
We're going to continue on with
our dating app journey and talk
about three more techniques.
And so, the first thing I want
to talk to you about is what do
you do when you got a view
controller and you've got a
navigation bar and a tab bar and
you want to make sure your views
are positioned so that they're
not covered up by those bars?
As you may have heard, there's a
new layout guide on iOS 11
called the Safe Area Layout
Guide.
It is a new property on UIView.
It works with Auto Layout and
what it is is a rectangle that
is around the bars and container
edges and then you can constrain
your views as you expect.
If you had to do this thing in
the past, you may remember the
Top and Bottom Layer Guide on
UIViewController.
Those are deprecated in favor of
this new safe area.
The Safe Area Layout Guide is
easier to use.
It's more expressive and allows
you to do a few new things, like
be able to center vertically
between your bars.
And that way as the [inaudible]
and the size of your height
changes, say if you rotate in
landscape, your layout will
adjust accordingly.
The Safe Area Layout Guide is
also something that can apply to
tvOS.
When you target your app and
your content for tvOS, you're
going to want to fill the big
screen.
The thing you have to consider
is that you're going to be on a
wide variety of displays from
small ones to big ones, flat
screens to projectors, and you
need to worry, in video terms,
of something called the overscan
region.
On some displays, my title here
can be cut off because it's too
close to the top.
And so you want to adjust your
content so that it's within the
safe area.
And the Safe Area Layout Guide
is going to represent this
region in iOS 11 for your tvOS
storyboards.
Just constrain your views to the
content and set it into the safe
area and then fill the rest of
your view with the beautiful
background imagery for your
users.
It's really easy to enable Safe
Area Layout Guide in iOS 11 and
Interface Builder.
You can go into your storyboard,
go to the file inspector, find
that box that says use Safe Area
Layout Guides and check it.
What's going to happen is that
the top level view of each of
your scenes is going to have the
new Safe Area Layout Guide, and
then you constrain to it just
like you would to other things
inside the canvas.
The Safe Area Layout Guide is a
new property on UIView for
keeping your content unobscured
and title safe, and, if you use
it on iOS 11 with -- for iOS
storyboards, will automatically
upgrade your constraints for you
when you check that box.
Thank you [applause] and that is
because the geometry between the
old Top and Bottom Layout Guides
will match the new Safe Area
Layout Guide.
And best of all, that also means
when you use Safe Area Layout
Guides on storyboards in Xcode 9
we'll make it sure it's
backwards deployable to previous
iOSs.
[ Applause ]
Now I want to talk about a
layout technique for being able
to position yourself relative to
your superview.
This is called proportional
positioning.
And the idea is say if I have a
dates' card in my dating app and
I want to be able to position it
about 70% down from the
superview.
How do I do this?
There are a few techniques
available.
The one I want to show you today
is the idea of using a spacer
view.
Dragging out a view, just a
normal UIView from the object
library.
Constraining it but not
rendering it.
And allowing it to be the
scaffolding for positioning your
view in place.
And this technique also applies
to other type of layouts that
are used in proportion.
Here's another example, where
I've got a landscape view, with
a 1/5, 2/5, and 2/5 proportion.
And then they're centered along
those proportions.
So let's go ahead and take a
look at how to do this inside of
Interface Builder.
So I've got a basic layout
already here.
And, in this case here, I want
to be able to position my date
card.
And it's being pushed in by a
form sheet with the modal segue.
So we're going to zoom in a
little closer over here, and
I've got two elements that
already have some initial
constraints.
I've got a label and I've got an
image.
And if we select them both, if
you look really carefully,
you'll notice that it's blue on
the left and right edges but the
top and bottom are red.
That means there's some work
that we need to do.
Whenever you see red in the
Interface Builder canvas, it can
be one or two things.
Either you have too few
constraints and you're
ambiguous, or you have too many
constraints and you're
conflicting.
I just set this up so I know I
haven't positioned myself
vertically in the superview.
So let's go ahead and do that.
And we'll do it by creating the
spacer view.
So I'm going to type UIView in
the object library.
Just drag out the view and
position it.
We'll give it just roughly the
place that I want to see it in
the canvas.
Next, let's do a few setup
things.
First I'm going to mark it as
hidden.
This is going to [inaudible] a
layout in runtime but we don't
want [inaudible] and that way
you don't incur the cost of
drawing.
The other thing I want to do to
recognize it is, in the object
library, rename it to spacer
70%.
Now we need to add constraints.
So I'm going to click on the pin
menu.
We're going to add a top
constraint, a leading
constraint, and then maybe give
it a width so I can do
constraint connections to it.
Add that. And you can see that
it's already moved horizontally.
But we still have the top and
bottom edges that are still red,
and that's because we haven't
specified a height yet.
We want to make this proportion
of the superview, so let's go
ahead and do that.
I'm going to add a equal height
constraint by dragging out from
the spacer to the superview and
choosing equal heights.
Now it's using equal heights to
my superview, but I realize I've
got a navigation bar up there.
And I actually wanted equal
heights to -- well, actually,
let's go ahead and set the
proportion.
And the thing is I'm still
relative to my superview, and I
want to be relative to my safe
area.
And so normally you'd have to
rebuild the constraint to do
this.
But I want to show you something
new.
If you go up into the attribute
inspector, which is a really
powerful thing, and you click on
the item, we list now the
neighbors that you can retarget
your constraint items --
[ Applause ]
And so if I hit safe area, you
can see it's now 70% to my safe
area.
Now let's go ahead and align our
content.
And so I'm going to take my
dates' label, drag it over --
create a connection using
control drag and align it to the
bottom.
Now I wanted [inaudible] nicely
along the baseline and so again,
all I need to do is click on the
constraint I just added.
Go to the attributes inspector.
And go ahead and set this to the
other attribute.
The really neat thing about Auto
Layout is you don't have to do
just bottom to bottom.
You can do something like bottom
to top.
Or, in this case, since I have a
single line label, I'll do
bottom to first baseline and
that way, now we're 70% sitting
right along the baseline.
Let's test it out in a few
configurations.
So iPhone seven plus portrait
using the device bar.
And let's take a look in
landscape and we're 70% there.
And so this is what I want.
So when you need to do this
proportional technique in
Interface Builder, use spacer
views to be able to get you
there.
And you be sure to mark those
views as hidden so that they're
not [inaudible] rendering but
are assisting you at layout to
be able to position your
content.
And if you're doing your layout
programmatically, the thing you
can use is the UILayout Guide.
And so programmatically, you can
use this as the equivalent to
the spacer views.
Next. Let's go ahead and talk
about another type of view that
we want to layout.
In this case, we're going to
show you an example of adaptive
layout in our dating app, where
we've got this view of a 4 x 4
grid giving me a selection, and
then it's got a label at the
bottom.
But when I rotate my phone, it's
actually going to give me
something a little different.
It's still going to give me the
4 x 4 grid of my dates, but it's
going to have a text view over
on the right.
So let's go ahead and see how we
could do adaptive layout using
stack views in Interface
Builder.
Okay. So I've got my dates
storyboard over here and pretty
much I've got this grid with an
initial layout set up.
I'm going to go ahead and first
expand the object outline.
I can hold down option and kind
of expand everything all at
once.
And [inaudible] give you a tour
of the setup.
We have a vertical stack view
and it's tied with four
constraints to the superview.
And then it's got three rows,
essentially.
The first row is a nested
horizontal stack view of the two
images.
Second row is also a nested
stack view of the two images.
And then the third row is a
label.
Now you can see that
everything's kind of equally
sized and that is because stack
view has these great properties
like alignment, distribution,
and spacing.
And there are a lot of options
for being able to configure your
layout using stack views and
nests of stack views.
The great part about stack view
is that it manages your
constraints for you so there are
very few constraints that you
have to add.
If you want to find out more
about the other, distribution
and alignments options, be sure
to check out the documentation.
Right now we're using fill
equally to make sure
everything's properly sized.
And let's go ahead and tune this
closer to what I want.
Okay. So let's first adjust for
spacing.
So I'm going to select all
[inaudible] command and select
all my stack views.
And then we're going to give it
a slightly larger spacing here
in the attribute inspector.
I'll set it to maybe 30.
That's a little too big.
So a new to Xcode 9 and iOS 11,
we have a standard spacing
option that allows the system to
choose for you.
I'm going to use that.
Now, if you remember back to
Jonathon's talk about dynamic
type, be sure to check out
standard spacing for vertical
stack views using content that's
using text styles and checking
this baseline relative.
You'll get the same effect of
dynamic type that you just saw.
For us, since we have images and
labels, we're going to go ahead
and just leave it unchecked.
And the next thing I want to do
is I want to really make sure
these images are square.
Now they may look square to you
but they really aren't, and I'll
prove it to you.
I'm going to control drag from
the image to itself and select
the aspect ratio constraint.
And you can see when I pop this
open it actually says a
multiplier of 193 to 226.
Let's go ahead and make it 1:1.
Okay. But something didn't quite
happen there.
Nothing happened in canvas and,
in fact, my aspect ratio is red.
And what's worse, if you take a
look over here, there's a little
red dot.
And so, when we click on that,
we have a whole bunch of
conflicting constraints.
What happened?
Well, let's go ahead and debug
this together.
And I'll give you -- we'll show
you a technique for how to
approach this type of problem
within the canvas.
So I've got the aspect ratio and
I want to, first of all,
validate that this is the thing
that introduced error.
Some I'm going to go to the
attribute inspector for the
constraint and then toggle the
installed button on and off to
see what happens.
And so, when I toggle it off, my
issues disappear.
And when I toggle it on, they
appear again.
But nothing's really happening
in the canvas, so the next
strategy I'd like to do is I
like to poke around in my
layout.
And the thing I care about is
probably the other red
constraints that are nearby.
Let's go ahead and take a look
at the one from the outermost
stack view to the top.
And when we uninstall that, the
issues disappear but we're no
longer fitting in the superview.
But the images are nice and
square.
That's kind of an interesting
effect.
Let's go ahead and do another
one.
So I'm going to reinstall this
one.
And I'm going uninstall the
trailing constraint.
And you can see again we're
square but this time we're
overflowing our superview.
And so what's actually happening
is that we can't satisfy both
the aspect ratio constraint, the
fill equally distribution on the
stack views, and then have it
fit into the superview.
Luckily, for my case, I don't
need to fill the entire
superview.
What I really want is actually
to just stick to the top.
So if I uninstall this, this is
closer to what I want.
But supposing we rotate in a
landscape and my height gets
smaller, I still want this
constraint so [inaudible] that
either.
And so what I'm going to do is
I'm going to leave it installed
and set it to greater than or
equal to, and then this is more
of what I want in portrait.
Let's go ahead back to the
object outline and we're now
going to look at landscape.
When I click the device bar on
landscape, you can see there's
some work that we have to do
here.
The first thing we need to do is
we want to get closer to the
look that we were wanting.
And, if you remember, the top
[inaudible] label needs to
disappear, and then we're going
to eventually put a text view
over on the right.
So let's first work on the top
[inaudible] label.
I'm going to click on it and a
stack view -- the thing we could
do is we could use the hidden
property.
Stack view is really great with
hidden subviews because it will
also collapse their layout but
keep them in the arranged
subviews array.
Now, we'll go over to hidden
property, and actually new to
Xcode 9, we also allow you to
vary this by size class.
And so you can see --
[ Applause ]
There's a plus button to make
that easier.
And so I'm going to pop it up
and choose any width.
And in this case, because it's
landscape, it is compact type.
You could also verify that with
the device bar on the bottom.
Right now we're in landscape
iPhone seven plus with regular
width and compact type.
So for any width compact type,
I'm going to add a variation,
mark it as hidden, and there we
go.
And, if we switch over to
portrait, it appears.
Going back to landscape, it's
disappeared.
Okay. We need to add our text
view now.
And, in order to do that, we
need a outer horizontal view.
We need some sort of horizontal
stack view for being able to
host the text view.
So I'm going to select
everything here.
And then I'm going to type text
view in the object outline
because I want to add that in.
Let's go ahead and embed the
outer view using the embed and
stack button.
So it created a new stack view,
and we need to switch it over to
be -- that's vertical.
We need to switch it over to be
horizontal.
Everything shrunk down because
also, since I embedded it into
new view, it got rid of my
constraints to the superview.
So we need to make it
horizontal.
Let's go ahead and give it a
standard spacing for the
outermost one we just created.
And then we can add a new text
view.
So we'll just go ahead and drag
that in.
There it is.
And then we need to rebuild the
constraints to our superview for
the outermost one.
So I'm going to go back to the
pinning menu 10, 10, 10, 10.
And then the bottommost
constraint, if you remember --
I'll zoom in here -- is going to
be greater than or equal to.
Okay. And so this is what I want
for landscape.
When we switch back to portrait,
we actually have to do a similar
thing and hide the text view by
a size class.
And so we can click on this.
Go over to the hidden menu again
and add a variation --
Of any width, regular height,
and then mark it as hidden.
And now we have the look that we
want.
[ Applause ]
So use the stack view, when you
can, for all your layouts.
Alignment, distribution,
spacing.
Those are properties that will
get you there, including
nesting.
Add just a few constraints.
We only noticed it needed aspect
ratio constraint to get the
proportion.
So you only need a few
constraints to get you a little
bit extra if you have some
requirements like the
proportion.
The hidden property in Xcode 9
is size classable, which is
great.
You can go ahead and use it, and
it works great with stack view,
because stack view will collapse
hidden subviews.
And best of all, varying by size
class with the hidden property
is backwards deployable.
[ Applause ]
So, in summary, we've looked at
six techniques today, and this
is going to add to your arsenal
for being able to build out your
apps.
We cannot wait to see what you
build.
And today we looked at some
techniques for being able to do
dynamic layout within the
runtime.
Things like dynamic type, as
well as layout techniques, for
being able to handle and make
your content look great,
unobscured, and handle adaptive
layout.
For more information, you could
check out the
developerapple.com.
If you want to learn more about
dynamic type, you could check
out the session this afternoon
and there are also links to past
videos.
Have a wonderful WWDC, everyone.
[ Applause ]