Video hosted by Apple at devstreaming-cdn.apple.com

Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2012-219
$eventId
ID of event: wwdc2012
$eventContentId
ID of session without event part: 219
$eventShortId
Shortened ID of event: wwdc12
$year
Year of session: 2012
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2012] [Session 219] Advanced Co...

WWDC12 • Session 219

Advanced Collection Views and Building Custom Layouts

Essentials • iOS • 54:43

Collection views in iOS 6 allow you to move beyond table views to create rich displays for ordered data. Dive deeper into the capabilities of collection views and learn how to write customized layouts that push the boundaries of interfaces in your applications.

Speakers: Olivier Gutknecht, Luke Hiesterman, Mathieu Martin

Unlisted on Apple Developer site

Downloads from Apple

HD Video (398 MB)

Transcript

This transcript was generated using Whisper, it may have transcription errors.

Welcome to Advanced Collection Views and Building Custom Layouts. I'm Luke Hiesterman. I'm an engineer on the iOS Frameworks team. And let me tell you, in less than 24 hours since we introduced Collection View yesterday, the feedback has just been overwhelming. And I can't tell you how excited that makes all of us to share with you the keys, the more advanced keys to Collection View so we can send all of you on your way collection view experts and creating just astounding UIs. So that's what this talk is going to be about, the deeper keys.

And to get us through that, we're going to start by talking about some architectural things in UI Collection View. That's going to be kind of the meat of this talk, the drier part. But get us all on the same page in terms of how UI Collection View works, its terminology, and the workings of things under the hood, so that we can go forward. And from there, we'll talk about how we can really push the UI Collection View flow layout in great directions. We got a taste of this yesterday, but we'll see really the kind of things that we can do with it.

And for those of you who went back to your hotels or your homes last night and pulled out a sketch pad and started writing your mockup of the next great American layout, we're going to talk to you about the API that makes it easy to write custom layouts. There we go. Build your own layout. So to begin, let's talk about architecture.

Part of this is going to be review from what you learned yesterday if you went to the intro to collection views talk, but we want to make sure we're on the same page for dealing with the advanced concept. So let's talk about the views that are in a collection view. There are three of them. Most of you hopefully remember them. They are cells. They are supplementary views. And they are decoration views. And let's take a minute to make sure that we're really familiar with the sort of two two new terms: supplementary view and decoration view, 'cause that's not something we've dealt with before in the kit, and we want to make sure we understand what they are and how they're distinct from each other.

So this is a UI that you've probably seen before from the previous talk, and it has supplementary views as denoted by the Paris and Telluride markers that are metadata about these sections. Now, that's sort of what's interesting about supplementary views. They have metadata about your content, but they're not the content itself. But what's important about them is they do take data from the data source, and in that sense, they are data-driven.

Conversely, if you look at the background of this thing, that little shelf UI, we consider that a decoration view. And the decoration view is fully owned and defined by the layout object. It does not interact with the data source of your collection view in any way. The data source will not be asked to provide any data. And the layout defines this completely within its own world. So in that way, decoration views are layout driven as opposed to supplementary views which are data driven. The layout defines support for a supplementary view, but the heart of the view is going to be the data that is provided by the data source. So we have this thing, this other class that was alluded to in our previous talk, which is you have collection view layout attributes. And this is the thing we want to understand because if you're customizing layouts, this is the object that carries information from a layout to a collection view and ultimately gets applied to all the views in the collection view. So let's talk about that relationship. We have the basic class diagram that you're already familiar with, and the layout attributes is this little tool that the layout is going to use to define itself as a layout. Each of the views that any given layout wants to layout, it will define the layout information in terms of instances of UICollectionView layout attributes, one instance per view.

And those are going to go from the layout, handed over each instance to the collection view. And the collection view is going to use those instances, which define how to layout a view, to literally go layout those views. It will apply the layout attributes in a given layout attribute instance to a view. So what are the attributes that are contained in this object? First and foremost and very simply, we have center and size. You can define where this thing is on screen and how big it is. We also have a convenience accessor that defines most of these, which is frame. You can define it in terms of frame if you're used to that in UIView. We also have alpha. If you want to control the opacity of your views, you can put that in a layout attribute and it will be applied to the views. We can apply a transform. This is actually a 3D transform to any of the views. And that will get applied as well. Now one thing you might notice is now that we have a transform on these views, they overlap each other.

And you might say, well, they overlap sort of top to bottom now, but I might want the opposite. I might want the views on top to overlap the things on bottom as though it was laid out bottom up. And we have a way for you to specify how things are stacked if they, in fact, overlap. And we do that via zindex property on the layout attributes. The way that works is any z index, any view with a z index is guaranteed to be layout above a view whose z index is lower than it and below one is greater than it. So by default, layout attribute z index is zero. But if you specify one to be, say, z index of one, then it is guaranteed to be above all of the views whose z index is zero. But if there was another view that was 2, the 1 would be guaranteed to be below 2. And in cases where they're equal, their stacking relationship is undefined. So in many cases, if you just don't have views that overlap, you leave the z index to everything as 0. It doesn't matter because they don't overlap.

Let's talk about how the layout gets information from the delegate. We talked about the idea that the layout gets information from the delegate in yesterday's talk. We talked about all these things that you can specify dynamically in the layout that the -- or in your delegate that the flow layout will use. And so the way that works is if this is our set of classes, we want effectively the layout to be able to draw this line and go directly to the collection view. And that makes it so that we can have a delegate, which is the collection view delegate, but then reuse that delegate for the purposes of whatever delegation needs that a given layout has, like the flow layout uses this to get dynamic sizing and other properties for itself. So how this works is a pattern that we are putting forth called basically the extensible And it is, in fact, true that this is not your granddaddy's protocol. And that happens by taking a concept that we already have, which is, say, the UICollectionViewDelegate extends UIScrollViewDelegate. This isn't really a new idea. UITableViewDelegate extends UIScrollViewDelegate in this way also. And that way, your delegate for the collection view can implement any of the methods defined in UIScrollViewDelegate.

So we take this a step further by saying that UI collection view flow layout defines its own delegate protocol called UI collection view delegate flow layout. And that protocol extends UI collection view delegate. So now you can set a delegate on the collection view which actually implements UI collection view delegate flow layout. And not only can it handle all of the collection delegation, but it can also handle the requisite methods for dealing with dynamism in the flow layout.

Now, since you're all here at the advanced talk and you're thinking about doing interesting things with layouts, you might write layouts that also want to get information from a delegate. And we want you to follow this same pattern. So you might have your own delegate protocol, and you would extend one of our delegate protocols with yours. So if you subclassed UI Collection View Flow layout and you wanted additional information from the delegate besides what is already there, you would make a delegate protocol that extends UICollectionViewDelegateFlowLayout. Alternatively, if you were writing a completely custom layout but you wanted delegate information, you could define a protocol that extends UICollectionViewDelegate, and that would be the protocol that you would use.

So that's the delegation pattern. Let's look at now how we change things in a layout. Some of the demos that were shown yesterday like Cover Flow deal with actually changing how things are laid out after the collection view is already on screen. And we have a mechanism for this. What changing things -- changing how things are laid out, which really is changing any of the layout attributes, after your layout has provided a set of layout attributes, it might want to say, well, I changed my mind about some of those or all of them. We consider that invalidation. That's what we call that whole idea is invalidating the layout. When you invalidate a layout, that means start over, provide new layout attributes, new layout information for the collection view to use.

The way to this is a method defined on the layout class called invalidateLayout. Now, we can get to the point where we're calling this a variety of different ways. One, if you're the delegate, say, you're the controller and you implement the delegate protocol, and maybe you have some dynamic sizes that you provide and size for item and index path, and you decide you change your data model, you want to change those sizes, well, you can just call invalidate layout on the layout after you've changed your internal model, and that will cause the layout to rebuild itself, including accessing your delegate again so that your new sizes can be applied.

You can also do this if you want to animate by putting that in a perform batch updates. Let's say you change your data model so that your sizes are going to be different now. But you don't want to just snap to those new sizes. You want the collection view to animate that. Well, perform batch updates is a block-based analog to begin updates and end updates from UITableView. And if you call this method, it will implicitly invalidate the layout. And whatever changes that you have put into your model will then get animated. You could also do this by, like, in there, in that block, you could then set a property like item size on the layout if it's UICollectionView flow layout. The layout can also call invalidate layout on itself if it wants to. Like if you just set the property of item size on UI collection view flow layout, well, that means that things should look different since you just changed the item size and the flow layout will call self invalidate layout because it knows that it is now invalidated and needs to invalidate itself. We provide one other mechanism which is a the convenience for layouts that want to define times for themselves when they need to relay out because of the bounds of the collection view changing. Now there are two main instances where this applies, which is one when you're scrolling, as you scroll up and down or left, right, whatever it is, that changes the bounds of your collection view. And if you're something like a cover flow, as you scroll, we want to change those transforms on the views, so that's changing the layout And we do that by responding to a method which is should invalidate layout for bounds change. If you have a layout like the cover flow that every time the bounds changes for a scroll it wants to relay out, it can return yes to this method and that gives it an opportunity to relay out. If you have something like the flow layout, the flow layout actually needs to reflow when the aspect ratio of the collection view changes, when you rotate from portrait to landscape. It needs to reflow. There can be, say, more columns if you have a vertically scrolling flow layout. So flow layout implements this method to check to see if the width has changed, say, if you have a vertically scrolling layout, and if the width of the bounds has changed, it says, "Yes, I need to invalidate," and it relays itself out in response to that. So that's the underpinnings of how Collection View works. And now that we kind of got that in our stomach, we can talk about stuff we can do with it.

And this section on advanced flow layout is pushing you towards the direction of when you go and start writing your custom stuff, I know that you have brilliant ideas and I want to direct you towards first thinking does my brilliant idea apply towards building based off of the flow layout. And the answer to that question is, well, it stems from the definition of the flow layout.

The flow layout is a line breaking layout. And if you have any variation on a layout that lays things out on a line and breaks when it gets to the end, then that's something you should start with flow layout. We showed you yesterday how to tweak the properties and the delegate methods on the flow layout delegate to be able to do cool things. Today we're going to dive into a more advanced way of customizing the flow layout which is subclassing and we can do even more than that. And the goal is to get you to realize just how much you can do by leveraging the work that we have already done for you in defining your collection view flow layout. And then we'll talk a little bit later about sort of going off into the other world.

So what are things you might subclass to do the flow layout to do? Well, you can add new kinds of views. We saw the decoration view that was added to this view. This can really be thought of as a flow layout. We have this sort of grid-ish thing, a flow of lines, and it's got that shelving behind it to make it look like a bookshelf application. And that's just something you can do in a subclass of the flow layout. You use the subclass to add additional views.

You can also use it to tweak the layout attributes. If you want to take the layout attributes that flow layout provides by default and change them a bit, you can do that. That gets you something like this or whatever it is that you want to define. Here we've tweaked the transform attribute. You can tweak any of the attributes you want like alpha or whatever it is that makes sense for your application to be able to get something super easily. This is only a couple of lines of code to modify the transform and I've leveraged everything that is already provided by the flow layout. Additionally, you can provide new layout attributes. One of the features of having this sort of layout attributes class is that you can subclass that class, UICollectionViewLayoutAttributes, into some new thing that adds additional layout attributes themselves. And you can use that. We actually shuffle the layout attribute instances over to cells and views themselves and call a method on them that is called apply layout attributes. And that allows you to use the layout attributes instances as a means of vectoring data from your layout all the way to the views and do special things with that. So if we look at this view, this is an extremely basic flow layout with a couple of columns. And we see there are little labels in each of these views that just tells me what index path they are. Now I can subclass the layout attributes class, provide a new instance that provides some additional attributes that my cells are programmed to know how to deal with, and then I can do something like this, where I have actually moved the justification of the text based on which column the cell is in. And the layout class was able to know what column it was laying things out in and then put an additional layout attribute into those instances that the cells could then read and say, oh, okay, I'm on the left or I'm on the right. In addition to justification here, I actually rounded the corners.

So the views on the left have rounded corners in the top left and the top right. Maybe a little hard to see. I don't know. And likewise, the views on the right have rounded corners on the top right and the bottom right. So that just gives you a taste of whatever information you might want to shuttle from your layout to your views can be done by putting that information in a subclass of UICollectionViewLayoutAttributes.

So you can also add gesture support by subclassing. You can just take a stock UI collection view flow layout and add to it a subclass that knows how to deal with a gesture. You saw in the introductory talk, Olivier had a layout that you could pinch and move cells around. Well, you could have a gesture support directly in the flow without having to write a completely custom layout. And you can do something like this, where you pinch on one, and then you are able to pinch out and just change the layout attributes of that one cell while still using all the other information from the flow layout class.

So you can also do this to add custom insert and delete animations. We saw this yesterday, which is a layout that if you recall is able to insert by taking photos in from the center. This shot is a mid animation shot of the center of the photo being inserted by animating in from the center. And this layout also would explode pictures as they animated out. This isn't a flow layout, but you can implement the same genre of strategy simply by subclassing the flow layout and overriding appropriate hooks to get custom insert and delete animations into your application and just add that bit to the flow layout. So these are all piecemeal things and they can, of course, be combined together that are the type of thing you can do by subclassing the flow layout. And really what makes this category of customization nice is all of these are just really a couple of lines of code. You're leveraging all of the work that UI collection flow layout does for you and just adding the thing that makes your app awesome. So that's really cool. And I'd like to invite Michu Martin up at this point to show us a demo of the code for a pinch resizing gesture on full layout.

Hello. There's pretty cool stuff we can do with flow layout. I'm going to show you just how to subclass flow layout to add a small gesture recognizer to it and have a nice user interaction. All right. So here we have a very simple flow layout set up as a grid. And what Luc was talking about is we want maybe to add like a small pin shift gesture recognizer to do something like that. And it follows my fingers. You could add also like a rotation angle if you wanted to, but here we just had an offset and a zoom scale on it. It goes back.

and can pinch any cells visible. So as Rick mentioned, it's not very difficult to do something like that, to extend some of the layout classes we provide to do this effect. So the first thing you want to do is to implement -- to have a function that handles your pinch recognizer. The only very interesting thing we're going to add to the layout are those two properties: Pinch Cell Class and Pinch Cell Center.

So when you override UI collection view flow layout or any layout for that matter, there's two methods to implement to override. The main one is layout attributes for item at index pass. That's the main function we're going to call and that return all the layout attributes visible in a certain rect. So basically your visible bounds. So there was this one, of course.

All right. So you can see that's the only code we had to write to subclass and to extend UI collection view flow layout. The first thing you want to do is to grab what the super class is doing. So you just call super with the same method. And then with the information you have given the flow layout subclass from your pinch recognizer, we're going to apply those values to the cells, to the cells attribute. Basically, what we are doing is, if we are applying the, dealing with the pinch cell, we just apply a transform, and we offset the center here.

So there's a little bit -- So as I said, there was two methods you want to override. And so the main one is really the layout attributes for elements in Rect. But the second one is quite important, too. At any given time, the Collection View can call back your FlowLayout or your Layout who is asking for information about a very specific cell. And we're going to ask you that for an index pass. And here, you need to do the same thing and apply the same transform and the same center offset to the cell.

So really, when you want to add a bit of user interaction to the flow layout, for example, you have only a couple of lines of code to write. Here if you see, the layout subclass is three functions, three methods, plus some glue code here at the bottom. But it's really like about 50 lines of code to add just a pinch -- a pinched organizer. And of course some bit of glue code in the controller. nothing you have to hack, or you can really do that in a very simple fashion.

Maybe we can look a bit more at the, at this thing. You see, any gesture, any cell can be pinched. And when we fail, when the gesture recognizer is, So, when I lift my finger, in this case, I go back to the regular layout. But in your delegate code, you could handle that the way you want. For example, trigger another action, maybe changing layout. Or even with the same example of flow layout, saying that this cell should be the entire width of your view, for example. There's a lot of things you can do with that. And as Luc said, before writing your own custom layout, and if your design fits in something that's either on the line or kind of grid-driven, you should consider subcasting your collection view flow layout. That's it. And thanks.

Thank you. Thank you. Thank you. All right, thank you so much, Mathieu. It's really that easy. I love it. So we're gonna move on to talking about maybe what some of you have been dreaming of for the last, I don't know, 16 hours. Yeah. And that's writing something totally brand new, amazing us all with your brilliant idea for the layout that is going to change the way we think of user interfaces on iOS.

And the value proposition that we're bringing here with UI Collection View is that we've taken all of the performance lessons that we've learned from things like building UI Table View, and we've brought it to UI Collection View and abstracted out this idea of defining how things are laid out in that world.

So when you go write some great layout, and then you go apply it to code or even, you know, hand it off to another engineer, another team of engineers, to say, "Hey, take this great layout that I wrote "and apply your data set to it," and they can go do that instantly and see the results. You don't have to spend your time implementing all of the performance features and things like cell selection that you would have to do otherwise if you started from scratch writing something like a grid view on iOS 5.

I've gotten, you know, just in the last two days, I've talked to a lot of developers who have written grid-type applications, and they come to me and they say, man, this thing is There's a good chance, you know, if you've dealt in grid worlds, you're in one of two situations. Either it's slow, in which case, introduce UI collection view, it's fast. Or you actually have really spent a lot of time on your grid view, and your grid view is fast, Introduce UI Collection View, now you manage less code. So either way, this is the thing for you if you're writing fantastic layouts.

So the first decision is, okay, we've talked a lot about flow layout. We've really pushed the advantages of subclassing flow layout in that by going down that route, you don't have to write a lot of code. You get a lot of things for free. But your layout idea is just so cool that it completely jumps the bounds of flow layout. It was not something that mere mortals like me were able to imagine when we designed Collection View. So you're... thinking, geez, should I just write a completely custom layout? And the decision for that is really based on, like, are you changing all the cell positions to the point where the flow layout doesn't make any sense for you anymore? You're just not buying anything from it? And you have something that just doesn't look anything like a grid. Maybe you have something that looks like this. You know? That bears no resemblance to flow layout. And so if you're doing that, okay. It's time for you to write a fully custom layout. And the good news is, even though you're sort of declaring yourself God and writing everything, The API is quite simple. And that's the other advantage of UI Collection View is we've defined a very succinct set of methods and a framework for thinking about defining layout information in addition to handling the work of performance and enabling cell selection capability and things like that so that you can focus your creative energies on building the best definition of a layout. and we have the framework for you to define that layout. So if you're in this world, you are going to subclass an abstract class that we are shipping called UICollectionViewLayout. This is a superclass of UICollectionViewFlowLayout, and as an abstract class, there are a handful of methods that you're required to override when you do this, so we'll talk about those now. Number one, UICollectionViewContentSize, or CollectionViewContentSize. This is where you tell us is the user's scrollable area in the collection view, the area in which you are going to lay out content so we know how to set the content size and where you might put content within this collection view.

Number two, you need to give us layout attributes for elements in a given rectangle. This is going to be the meet method. This is, I dare say, the single most important method on UI collection view layout. It is the thing that we're going to call when we bootstrap up the collection view to ask how to lay things out. And here you're going to provide us an NSArray of UI collection view layout attributes. And we will take those attributes, which define how to lay things out, and go apply them to views. Additionally, as Mathieu mentioned before, we will from time to time require direct access to the layout attributes for a given item. So you're required to implement layout attributes for item at index path.

This is sort of the, you know, quick way instead of going through layout attributes for elements in Rect. Additionally, we have direct accessors for supplementary views and for decoration views. So if you support supplementary views or you support decoration views, you're also required to implement these direct accessors as appropriate.

Let's talk about the order of operations in which UI Collection View will call these things. We're gonna start by calling prepareLayout. This is an optional method. It's not one of the required ones. But this is the opportunity for your layout to do upfront calculations regarding however you're going to lay things out. And for example, the circle layout that we saw in the previous session's demo PrepareLayout might figure out how many cells, how many elements are in that circle and determine based on that what the radius offset it's going to use for each item, and it can use that radius offset in computing individual item attributes later. Or layout might compute everything about itself. It might store off layout attributes in a dictionary or an array somewhere. So this can be whatever you want, as much upfront calculation as you want, or it can be as lazy as you want. You can choose to ignore this method and do all of your calculations later when we ask you for layout attributes for elements in rect. Next thing we're going to call is CollectionViewContentSize. We need to -- after you're prepared, we need you to tell us, hey, what's the area in which you're going to lay stuff out?

After we have that area, we set the content size of the collection view, and we will call that most important of methods, layout attributes for elements in rect. This is when, okay, it's time, we're going to display stuff on the screen. We need to know where to put it. And, in fact, what stuff is on screen. So we're going to pass you a rect that will at least cover the current screen. And you need to tell us what's in that rect and how to lay it out.

pass this layout attribute instances. At this point--from this point, our layout is considered effectively live, if you will, and we can call any of the other methods that are defined on URCollectionViewLayoutAttributes depending on what happens in the flow of interaction and, you know, what is necessary for the given time.

until we hit at some point, the layout gets invalidated. This happens for any of the reasons we talked about before. The controller calls invalidateLayout, the layout calls invalidateLayout on itself. Whatever reason it gets invalidated, we call invalidateLayout. And that means start over. So after that point, we go back to the beginning. We will call prepareLayout on your layout again. It will give you a chance to redo any of those calculations that you threw out in invalidateLayout because you won't need anything again after invalidateLayout, and the cycle continues. We start over, we do that same thing again, just a few methods, and it's really just within this very simple framework that you can provide to us layout attributes for whatever you might need, defined in whatever way makes sense for you, provides a nice, simple way of separating definition of a layout from all the other great features that are supplied by CollectionView, and also makes it so that you can define a layout and ship it to somebody else who is creating content and creating a controller and a delegate and all that such. So that's just how simple it is. At this point, I would like to invite Dr. Olivier Gounest on stage to show us a demo of how all this works.

only two layouts yeah yesterday i may be forty two layouts in five minutes are going to be nice and quiet You know these iOS apps showing some kind of document browser? So you have this line of documents, and the thing at the center is a small zoom, scaled up? We need to do that. So it's a CollectionViewFlow layout. And what I did here is just set up an in-time size in my subclass and changed my scroll direction And so that's actually a horizontal scoring layout.

And in that case, it's just a very simple flow layout. Next thing I'm going to do is to adjust parameters on that flow layout. So I'm going to get only one line. So that should be, yes, much better. So now, I need this scaling effect. How do I do that? I'm going to use the exact same technique and actually reuse Well, the flow layout is going to define. And for that layout, what I want to do is Just grab the cell at the center of the screen and just tweak its attributes. So what I'm doing here is I check the actual -- Collection view bound size and its content offset. And I have this very boring mathematical stuff which just tries to find what is in this current attribute, which is the thing closest to the center. And then the only thing I need to do is to apply a zoom based on the distance for that cell which is closest to the center. Let's try that. Oh, that was better. Actually, no.

The thing I need to do now is, when I scroll my layout, when I scroll my collection view, I actually need to update the attributes for the cell each time I scroll, right? So, one thing I could do is to call invalidateLayout a lot, or... I can use this shouldInvalidateLayout for bounce change.

And in that case, connection view is going to invalidate that for me. So I basically have what I need here. Okay, maybe the one thing missing, if you want to nitpick, is: You remember my CoverFlow-like demo yesterday? I had this nice snapping behavior for the cell, so it would be perfectly centered. So I'm going to add that.

Let's take that first. Much better. So that method is a way to scroll view that is our superclass in CollectionView. It's going to communicate with the layout. So we actually ask-- the CollectionView asks the layout to compute that Target offset when we scroll. And the way we do that is We're going to get the cells in this destination rect. And... We're going to iterate in the destination right for the scroll We're going to find what cell, actually what layout attributes is the actual closest one to the center. And in that case, we just slightly tweak the offset for that cell. And that value is going to be used by the scroll view to actually adapt to target content offset. So, okay, what do we have here? One method, two methods, three, four in it. So with that amount of code, you can implement this very popular scaling effect in your line layout. Then-- That was a technique which is not tied to flow layout at all. You can use that for any of your custom layout. So let's check our custom layout now.

You might remember this one. So that is definitely not a line-based layout. So we set up in this one the layout attributes all self. And I also added-- couldn't resist-- a small animation for appearing and disappearing cells. So how do we do that? Let me just show you the actual view controller because we don't really have magic here. I just want to prove that. So I set up a gesture recognizer on my collection view. I registered the cell class, as we learned yesterday, and I set up a nice background color. And I think I have the most stupid data source implementation ever.

I just need a cell count. So I need 60 items. Okay. And my cell, because I don't have any content in that, I just dequeue and return my cell. Then... This tapping gesture, I'm using here a few things that Collection View can do for you. One thing is you can ask the Collection View what index pass is at a point in the view. So I just get the index pass for the cell I tapped.

And if I type that cell, I want that cell to go away. So my extremely stupid implementation of a data source is just going to decrement that cell count. And I'm going to remove in my collection view an item for that index pass. So if you use table view before, it's basically the same thing. It's block based, but the exact same mechanism we were using with table views.

And because I'm doing that with this blog-based method, it's just going to animate things. And if I didn't tap on a cell, well, in that case, that index pass returned by the collection view is going to be nil. So I just decided that when I tap in the background, I just want to add a new cell. So that's my logic. That was quite simple. Now, what about the layout itself? So, that's a UID CollectionViewLayout subclass. I just need a few things. The radius for my circle, where that thing is on screen. And I'm going to track a cell count in this layout. And you'll see why.

So, my two really important methods here, the one that we call when we set up a custom layout. First, prepareLayout. This is where we are... If you want to set up some initial attributes or compute a few things ahead of time, PreparLayout is the place to do that. And because that is a really simple layout, and because I'm lazy, that layout only supports one section.

And I'm implementing that by asking the CollectionView how many items do we want to layout. So that line is basically my configuration for my layout at a given point of time. Then my two other parameters is where should I display that circle and radius for that circle layout. And again, that's a very simple layout. And I don't want to scroll or anything. So the collection view content size I'm using actually is going to be just a frame of my collection view. So that's really full screen, no scrolling layout. And I'm using that to set up my center for that layout and the radius. And I'm ready to actually generate layout attributes now.

So that's our next method. So Luke said that when you're implementing a custom layout, you have two methods that you really need to implement-- layout for index pass and layout attributes for item at index pass and layout attributes for rect. And that layout attributes for item at index pass-- It's usually where you actually instantiate a layout attribute.

So that line -- whoops -- that line is just us constructing a layout -- a UI collection view layout attributes for an index pass. So you have this method, layout attributes for cell with index pass. We have the same thing for supplemental reviews and decoration views. And the next step is just to decide what you want to do with that layout attributes. So we just want to set up the size for that cell.

And the center part, where should we actually position that? So, mathematics again. And we're just using our cell count we prepared in the prepare layout phase to actually decide where each of these cells should be based on, basically, the index pass of that thing. So... What's happening here? Collection view needs layout attribute for a given index pass. Scrolling the layout with that index pass. We compute the exact position for anything that should be at that index pass. And these index pass are basically what are in your data source. And then we return the attributes.

So for my circle layout, that was quite a simple implementation. We have a perfectly mathematical layout. For things more complicated like my map example yesterday, you could generate that before in prepareLayout and just return a given layout attribute in this method. We have a lot of different strategies here.

And the next method I actually need to implement is layout attributes for elements in React. And again, that is a very simple layout because I want to display every single cell here. So that implementation is just iterating on the cell count. We are building an index pass for that item.

And then we need to generate for each of these index paths a UICollectionViewLayout attributes. And the good thing is-- We did that already. So I'm just reusing this layout attributes for item at index pass above to create that UI collection view layout attributes. That implementation is very simple.

So UI collection view is not magic. Not completely. So when you want to build your own layout, you won't -- probably you won't be in that situation. You won't want to actually display every single item in your data set. Because that is going to be quite high performance cost. So when you have things like a stack layout that Luke had on the slide before or in my demo yesterday, you want to optimize that. You want to display a few cells, And after that... just cheat and not generate layout attributes for every single item in your data set. But with this form method-- we have a perfectly fine custom layout. And now we can add some fancy stuff, like these custom animations for inserting and deleting items in my data set.

And that's quite easy, actually. So you just have to override one method, which is initial layout attributes for inserted item at index pass. We absolutely love extremely long method names. And how do I do that? Well, initial layout attributes is going to be the starting point for a cell that I want to insert in my layout. So if we get back to this-- animation. What's happening here? So layout itself is going to reconfigure itself. And that is just calling -- that is just a collection view calling layout attributes for items in rect. And for this cell animation, what we actually do here is really simple. We just want that cell to start at the center and with alpha zero. So -- I just reuse again my layout attributes for item at index path method.

And I just tweak. It's a bit technical like what we did with subclassing for layout. Just reusing layout attributes and tweaking that. And I just change the opacity in the center. And what collection view is going to do, it's going to compute its final official position is a circle, and then compute that initial layout attribute, and we're going to animate from that initial state to that official state. And building this animation for the disappearing cell is actually quite easy, too. And in this case, if you remember, is when I actually tap a cell here.

What I'm doing is, again, reusing the same technique of grabbing the existing layout attributes for that index pass. I'm switching the opacity to zero. I'm, again, changing the position to be at the center. So I'm setting the center of the cell to be the center of my layout. And the only additional tweak is this shrinking effect, which is just a small CA transform 3D scale. So it's just a scaling transform.

So with these two methods, just a few lines of code, I have custom animation for ourselves going in and going out. And then to wrap this up, I'd like to bring back Luke on stage. Thank you.. I really hope you guys are as excited as we are about the possibilities that are being enabled by UI Collection View and really by your creativity, which is now going to be unleashed by the -- how much easier it is to define a user interface that is highly performant and has built-in features like selection and such on the cells. So to review the ideas that we really want to take away from this, remember just how powerful UICollectionView flow layout is. When you go out and start thinking about cool new things, remember that it's powerful, it's got a lot of bells and whistles that you can tweak in the delegate and its properties that we talked about yesterday, but it's also a a subclassable entity that you can add your own ideas onto based on the framework that we have already built for you.

And then, moreover, the fact that UI Collection View enables you to build completely custom layouts and define that layout code separate from all the performance optimizations and features that we have built into Collection View. So taking that framework, taking the work that we have done for you into building great user interfaces is something that I hope you'll enjoy, and I know I am incredibly looking forward to coming back a year from now and seeing what all the just spectacular interfaces you guys have come out with are. So thank you very much for coming and learning about CollectionView. Thank you. If you have more questions, direct them to Jake Behrens. He's our UI Frameworks evangelist. We have another intro session tomorrow. tomorrow.