Bummer! This is just a preview. You need to be signed in with a Basic account to view the entire video.
Start a free Basic trial
to watch this video
To implement pinch to zoom and panning we need to add a new view to our app. In this video, we'll get our first look at a scroll view and understand how a scroll view works.
Resources
-
0:00
[MUSIC]
-
0:04
The last feature we're going to implement in this app is probably the most
-
0:08
interesting.
-
0:09
Everything we did so far was a variation, or
-
0:12
level up, in some knowledge that we have already learned about.
-
0:15
Core data, data sources, and so on.
-
0:18
To implement pinched zoom and panning, we need to learn about scroll views.
-
0:23
Scroll views, in UI kit, while not fundamentally different from a regular
-
0:28
view, allow us to extend, so to speak, our views beyond the edge of the screen.
-
0:34
So far, unless we've used a class like UI table view, or UI collection view,
-
0:39
any views that we defined are restricted to the bounds of the screen,
-
0:43
to the screen size.
-
0:46
UIScrollViews lets you surpass this constraint, but it does so
-
0:49
in an interesting way.
-
0:51
So rather than just jumping right in and writing code to use ScrollViews,
-
0:56
let's take a second to talk about coordinate systems in views.
-
0:59
It's been a while since we learned about the coordinate system in iOS, so
-
1:03
first, a refresher.
-
1:05
UIkit defines a default coordinate system with the origin in the top left corner,
-
1:10
and axis extending to the right, and down from the origin point.
-
1:15
Views are laid out within this coordinate system to position and size them.
-
1:20
In addition to this Default Coordinate System,
-
1:22
which we'll call the Screen Coordinate System, an app's window and
-
1:26
views also define their own Local Coordinate System.
-
1:30
Let's look at a singe view, a view object tracks it's size and
-
1:34
location using a frame and bounds.
-
1:38
A frame is a rectangle, which specifies the size and
-
1:41
location of the view within its SuperView coordinate system.
-
1:46
A bounds rectangle, on the other hand,
-
1:48
specifies the size of the view within its own local coordinate system.
-
1:53
Let's give this views some dimensions, a width of 100, and a height of 80.
-
1:58
In terms of the properties we talked about earlier,
-
2:01
the views bounds is {0, 0, 100, 80}.
-
2:05
Since bounds is a rectangle, those value correspond to x-origin,
-
2:10
y-origin, width, and height.
-
2:13
What about the frame though?
-
2:15
Since the frame is how we talk about a view relative to it's SuperView,
-
2:20
that is the view that contains it, we don't have a frame here
-
2:23
since we don't have a SuperView, we just have the one view.
-
2:26
Let's go ahead and introduce a second view.
-
2:29
To avoid some confusion, we'll call the first one a button, so
-
2:32
you know which view I'm referring to.
-
2:35
Our new view has a balance of {0,0,120,100}.
-
2:39
Again, since this is a rectangle in it's local coordinate system
-
2:44
that means an origin of 0 0, a width of 120 and a height of 100.
-
2:50
Let's place the button inside the new view,
-
2:52
which we'll call something like GreenView.
-
2:54
Now in doing so, the button is now a SubView of the GreenView.
-
3:00
The GreenView is the button's SuperVeiw.
-
3:03
Since the button now has a SuperView, we can define its frame.
-
3:06
The button's frame, at the point that we've placed it, is {0, 0, 100, 80}.
-
3:13
You might have noticed that this is the same as the button's bounds.
-
3:18
When placed at the origin in a SuperView, a view's bounds and frame are the same.
-
3:24
Let's move the button around.
-
3:26
If we shift the button 20 points to the right, what does this change?
-
3:30
Since the bounds is the rectangle defined within the button's own coordinate space,
-
3:34
bounds hasn't changed at all by doing a translation of this view to the right.
-
3:38
The frame on the other hand, is now {20, 0, 100, 80}.
-
3:44
Since we shifted the button 20 points to the right,
-
3:47
it sits at an x-origin of 20, y is unchanged.
-
3:51
If we move the button down by 20 points, again the bounds are unchanged,
-
3:56
but now the frame is {20, 20, 100, 80}.
-
4:00
What happens if we shift the button to the right again by 20 points?
-
4:04
Now the button's frame now is {40, 20, 100, 80}.
-
4:10
Since the button's frame exceeds the GreenViews bounds,
-
4:14
the button is now clipped, [NOISE] and
-
4:16
we only see a portion of the button that is drawn inside the GreenView's bounds.
-
4:21
Okay, that's enough of our refresher, and
-
4:24
if this was new to you hopefully it all made sense.
-
4:28
So how does this play into scroll views?
-
4:29
Well if we look at our example here, the button is clipped,
-
4:33
because [NOISE] part of it is outside the GreenView's frame.
-
4:36
If we wanted to see the entire button again, we could adjust its frame so
-
4:41
that it's back in view.
-
4:44
If we decrease both x and
-
4:45
y origin by 20 on the buttons frame, the button would be back at its original spot.
-
4:51
Why does this matter, again?
-
4:52
Well this is one way in which we can simulate a scrolling.
-
4:57
So let's take a look at this example, but in the context of our phone screens.
-
5:01
So here the GreenView fills up the entire screen, and again, the button is only
-
5:05
partially visible, because [NOISE] its frame is outside the GreenView's bounds.
-
5:09
To mimic scrolling, we could track the user's finger movement across the screen,
-
5:15
and adjust the buttons' frame by the amount of that movements.
-
5:19
If I scroll from right to left,
-
5:21
I can modify the buttons' frame's origin values to bring it back into view.
-
5:27
Now, if that's confusing to you, and I'll be honest, this is a confusing topic.
-
5:31
Think of it this way.
-
5:33
You have a house with an object inside, and a window looking into the house.
-
5:38
The window represents the mainView, while the object represents a subView
-
5:43
of this mainView, just like the button was a subView of the greenView.
-
5:48
Right now, we can see a single object through the window, a chair, but
-
5:51
only part of it.
-
5:53
Much like we adjusted the buttons' frame, we can move the chair around
-
5:57
relative to the window's coordinates to make it fully visible.
-
6:01
The chair's role here is analogous to the button in the earlier example.
-
6:05
But there's a problem here, imagine that instead of just a chair,
-
6:10
this house is full of objects and we want to look at them.
-
6:13
If we took the approach we just did, moving the actual object into view, or
-
6:18
in iOS terms, modifying the frame of each view,
-
6:21
then to mimic scrolling we have a lot of frame adjusting to do.
-
6:25
So in the left corner of our room, there's a table.
-
6:28
To move that table into view we could push it over, thereby adjusting its frame.
-
6:33
But now all of the other objects are out of place relative to the table.
-
6:38
We need to maintain the layout we had earlier, so
-
6:40
we need to shift every single object in the room by the same amount.
-
6:44
In a complex view hierarchy, that's a lot of frame math and
-
6:48
adjustment that we have to do.
-
6:50
But there is another way, an easier way.
-
6:52
In the right corner of the room, there's a lamp.
-
6:55
If we wanted to see that lamp, instead of moving everything else in the room,
-
6:59
what if we moved the window over in front of the lamp?
-
7:03
Now I realize in the real world you can't just move a window, but bear with me.
-
7:07
Rather than moving every other object in the room,
-
7:10
by moving the window around we can see the parts of the room that we want to.
-
7:15
So let's try and relate this to actual views now.
-
7:18
Remember that each view has a frame and bounds.
-
7:20
Again, frame is relative to the SuperView's coordinates.
-
7:24
Bounds are relative to local coordinates.
-
7:26
So each object in this room has its own bounds rectangle, and
-
7:30
a frame rectangle [NOISE].
-
7:31
Frame rectangles are relative to the super view, so
-
7:34
each of them has a frame that determines where it lives in the super view space.
-
7:39
If the window is the main view,
-
7:42
then its bounds rectangle is as shown with {0, 0} in the top left.
-
7:47
So objects within that space have frame values relative to where this {0,0} is.
-
7:53
Now all of this time, we've been thinking of this window as a view that was defined
-
7:57
by this border, so let's modify that.
-
8:00
What if instead of the window, the entire wall was the view, and
-
8:04
the window is just the portion of the view that we see on the screen?
-
8:09
So far nothing has changed, except mentally we need to adjust for
-
8:13
the fact that a window now represents a slice of the view that we see, and
-
8:18
the actual view extends beyond the edges of the screen.
-
8:21
Let's make one more change.
-
8:24
Let's move this window to the top-left corner.
-
8:27
Since the entire wall represents the view, the window is now at x-zero,
-
8:32
y-zero, with some width and height.
-
8:34
If we move the window 20 points to the right, we're now at x-20,
-
8:38
y-20, and we can see a different set of objects.
-
8:42
What we just did was to move a rectangle around the view
-
8:46
within it's own coordinate space.
-
8:48
Since bounds is just a rectangle defined with a views local coordinate space,
-
8:55
all we're doing right here is modifying the main views bounds
-
8:59
when we move this window around, this physical window.
-
9:02
By moving this window around, that is by adjusting the bounds rectangle
-
9:07
within the main view,we can bring different objects back into view.
-
9:12
This is essentially how a ScrollView works.
-
9:15
When we add a ScrollView, we define its content size.
-
9:19
The content size of the ScrollView defines,
-
9:22
as the name implies, the size of the view that contains content.
-
9:27
This is also the scrollable area of this view.
-
9:30
Now the scrollable area doesn't affect the bounds of the view, but
-
9:34
it affects how large the view is.
-
9:37
So going back to our house analogy, the content size, or
-
9:39
the scrollable area of the ScrollView is the same as this entire wall.
-
9:44
The bounds of the ScrollView, which is our window in this example,
-
9:49
is the section of the scroll view that we see on screen.
-
9:52
When the content size of the ScrollView is larger than its bounds,
-
9:57
then we can scroll the view by moving or adjusting the bounds rectangle.
-
10:03
If the content size is the same size as the bounds, we can't scroll,
-
10:07
there's nowhere to go.
-
10:08
Now this way, if we have several subviews in our scrollable view,
-
10:13
rather than move the subviews around so they appear in the bounds area,
-
10:17
we can adjust the bounds to display different sections of the scrollable area.
-
10:22
Let's take a break here.
-
10:23
This is a lot of new information, which you've probably already forgotten or
-
10:27
gotten confused about, and that is totally okay.
-
10:30
Just rewatch this video, get a sort of general sense of it and how these parts
-
10:35
relate to each other, and when you're ready, join me in the next video.
-
10:38
Writing code will actually help cement this concept into place.
You need to sign up for Treehouse in order to download course files.
Sign up