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
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
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 Views so we can send all of you on your way to being Collection View experts and creating just astounding UIs. So that's what this talk is going to be about, the deeper keys.
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 these sort of two new terms, supplementary view and decoration view. Because 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 UI Collection View Layout Attributes. And this is the thing we want to understand. Because it's a very complex thing.
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 game is going to use is going to be defined as a layout. And if any given layout wants to layout, it will define the layout information in terms of instances of UI Collection View 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 both 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 zindex, any view, with its zindex is guaranteed to be layout above a view whose zindex is lower than it and below one that's greater than it. So by default, layout attribute zindex is zero. But if you specify one to be, say, zindex of one, then it is guaranteed to be above all of the views whose zindex is zero.
But if there was another view that was two, the one would be guaranteed to be below two. And in cases where they're equal, their relationship, their stacking relationship is undefined. So in many cases, if you just don't have views that overlap, you leave the zindex to everything as zero. 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 -- 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, "Oh, 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 delegate. And it is, in fact, true that this is a method that we use in the collection view. And this is not your granddaddy's protocol.
And that happens by taking a concept that we already have, which is, say, the UI collection view delegate extends UI scroll view delegate. This isn't really a new idea. UI table view delegate extends UI scroll view delegate in this way also. And that way, your delegate for the collection view can implement any of the methods defined in UI scroll view delegate.
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 View 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 UI Collection View Delegate Flow Layout. Alternatively, if you were writing a completely custom layout but you wanted delegate information, you could define a protocol that extends UI Collection View Delegate, 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.
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.
and David 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 UI table view. 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 UI collection view 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 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 attributes. 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, like 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're -- 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 a little bit more complex.
It 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 very specific flow layout, 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 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 was 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, UI collection view layout attributes, 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 then call them. And then we can actually shuffle the layout attributes instances over to cells and views themselves and then call them.
And then we can actually 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 into 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 -- 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 UI Collection View Layout Attributes.
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 know, you could have a gesture support directly in the flow layout without having to write a completely custom layout. And you could 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 View 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 Mathieu Martin up at this point to show us a demo of the code for a pinch resizing gesture on Flow Layout.
Hello. There's pretty cool stuff we can do with FlowLayout, and I'm going to show you just how to subclass FlowLayout to add a small gesture recognizer to it and have a nice user interaction. All right. So here we have a very simple FlowLayout set up as a grid. And what Luke was talking about is we want maybe to add like a small pin-shaped 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.
[Transcript missing]
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. 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. And basically what we are doing is if you 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, 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 flow layout or your layout was 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 in 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 about 50 lines of code to add just a pinched organizer. And of course, some bit of glue code in the controller. But nothing you have to hack. You can really do that in a very simple fashion.
Maybe we can look a bit more at the thing. Any gesture, any cell can be pinched. And when we fail, when the gesture recognizer 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 Luke 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 subclassing your collection view flow layout.
Is that it? All right, thank you so much, Mathieu. It's really that easy. I love it. So we're going to 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. That's five.
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 slow." Well... 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 FlowLayout. We've really pushed the advantages of subclassing FlowLayout 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 FlowLayout. 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 CollectionView 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 UI CollectionView layout. This is a superclass of UI CollectionView flow layout. 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, UI CollectionView content size or CollectionView content size. This is where you tell us what is the user scrollable area in the CollectionView, the area in which you are going to layout content so we know how to set the content size and where you might put content within this CollectionView.
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. 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 going to 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 Prepare a layout that 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 a 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 Collection View Content Size. 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 UI Collection View attributes, depending on what happens in the flow of interaction and 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'll call prepareLayout on your layout again.
It'll 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 Collection View. 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 Gutknecht on stage to show us a demo of how all this works.
Only two layouts. Yeah, yesterday I maybe did 42 layouts in five minutes. I'm 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 Collection View Flow layout. And what I did here is just set up an in-time size in my subclass and change my scroll direction so that's actually a horizontal scrolling 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. So. 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 "Should invalidate layout" for bounds change.
And in that case, Collection 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.
[Transcript missing]
So that method is a way to scroll a view that is our superclass in Collection View, is going to communicate with the layout. So we actually ask, the Collection View asks the layout to compute that Target offset when we scroll. And the way we do that is...
[Transcript missing]
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 offsets. 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. That was a technique which is not tied to Flow Layout at all. You can use that for any of your custom layouts. So, let's check a 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 you 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 CEL 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 path is at a point in the view? So I just get the index path for the cell I tapped. And if I tap 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 used 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 block-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 UI Collection View Layout 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, prepare layout. 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 Collection View 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 is just us constructing a layout of UI Collection View layout attributes for an index pass. So you have this method, layout attributes for cells 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 PreparLayout phase to actually decide where each of these cells should be based on, basically.
[Transcript missing]
What's happening here? Collection view needs layout 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 UI Collection View Layout 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. 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 React. 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 0.
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 and the center. And what Collection View is going to do, it's going to compute its final official position in the 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 and 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 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 UI Collection View 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 subclassable entity that you can add your own ideas onto based on the framework that we have. 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 Collection View. If you have more questions, direct them to Jake Behrens. He's our UI Frameworks Evangelist. We have another intro session tomorrow.