Welcome back again.
In this lesson we'll talk about advanced collection of your layouts.
So far everything that we did with layouts have been essentially with the a collection view floor layout
features the which is essentially like the medium level of managing allowed in a collection view.
There is another outlet that is called collection view layout which allows you to do really advanced
the stuff.
Now before I jump in to explore then show you how we going to code that I'm actually going to show you
the product that we're going to build.
This is an application that has so many image views each image of you is essentially a cell of a collection
view and the cells are arranged depending on the height of the images.
So each of the cells they essentially have a different image height and based on that they get a different
cell height.
Now the size of the vit in all of the columns are the same.
There are three columns but even that we could essentially go ahead and modify it collection view layouts
to allow you to do a lot of different things you could choose to have layouts that they have things
such as this one that the vertical height are different or you could have layouts that within a row
you would marriage some cells with each other and make essentially like a visor a longer cell.
So there's a lot of things that we have to do to get to this point is going to be a slightly longer
lesson and let's get a sorted.
The first thing I'm going to do is I'm going to jump into X court start a new application and say this
is an application that is a collection of you read at the vast layout not in my collection view with
advanced layout there are a bunch of things that we know how we have to do and before going to the actual
parts of the layout of I want to make an application that shows me these images and these are the images
that I have provided you guys as well and you could essentially copy any kind of images that you have
someone to copy all of these into my project and in your and wants to all copied in here.
I'm going to make a group of all of them so select all of them new group from selection.
I'm gonna call this one images.
Now the next thing is I'm going to get rid of my view controller.
I'm going to start a new file a new file which is off the Thai UI collection view controller.
I'm gonna call it my collection view controller.
So so far we have our collection view controller and then the next thing is I clean some of this stuff
in here.
They know I don't need them.
So for instance I won't need the view that load.
So we keep that part but then I don't need the number of sections I need the number of rows and I need
the sell for item.
Everything else can go essentially so just like all these three methods are number of rows sell for
IDM.
And of course if you did load.
And one more thing I want to do before I jump into the storyboard I'm going to make a new fine.
This one is a UI collection view sell UI production view cell and that's fun.
I'm going to call it my cell.
Simply because this is a cell that it has to show me an image of you retain it since it has to show
me an image of you.
Maybe I'll just make that one right away and when I say I'll be outlets are valuable my eye AMG view
of the type of UI image you view and then I'm going to head into my storyboard and in the storyboard
I'm going to go ahead and say Let's delete all of the at the outlet that we already have.
Let's make a collection view controller.
The correction view controller becomes my initial view controller and it has a class that is my collection
view controller.
Then I'm going to select the cell in here.
Say it has an IED cell IED just like what we do always.
Then I'm gonna go ahead and say it actually has a let me bring this here.
So if we have a my cell to be the class of this cell and then since this class has an image of you built
into it I'm going to make an image of you in here and say let's set all the constraints for it.
0 0 0 0.
So it's all there.
And then finally from my cell I'm going to connect a major view to this image view.
It usually helps if you've got your image view and say clips to bounce and use a mode such as aspect
Phil which is the one I personally like to use.
So we have a collection view the collection view has a cell.
The cell has an image view and now we can head into our view controller.
And in here we have to make an array of our images.
One of the easier ways if you copy these I should mention that there are ways to read the all the images
from a folder such as this one.
It's a slightly longer code.
So I don't want to do it in here but I would really encourage you guys to have a look at that because
you could essentially go on and read the file manager get the contents from an a folder and fetch all
of them into an array.
I find it a little bit more tedious than just typing it because it's really not a it's another scenario
that happens in real life application you often don't have images like this.
Your images are being fed to an application from a network or a backend.
In any case I'm going to see images in major names.
Let's say right because these are the names of the images.
They're not the actual images.
So these names are going to be me format this a little bit better.
So they all have a quotation at the beginning of them and they have this.
So that's I'm going to copy that say paste it in here.
I didn't do what I was hoping someone copied manually so dat dat dat dat dat dat dat dat.
And then at the very beginning of all of them and when I have to add a open quotation little bit of
extra a Lake Worth both kind of unnecessary.
So now we have all of our images or major names within an array and then in another area.
And that is the actual images are.
So I'm going to say this is valuable images array which is an array of you I image you I image and that
one actually is an empty one right at the very beginning.
And this is all images that we need to to essentially have in our collection view.
So the next thing I'm going to do is I'm going to go in here and say VIN I HAVE MY VIEW THE LORD.
Let's go ahead and read all of those images and place them within our image array.
So I'm going to go ahead in here and say for any in images array names and do this say images array
that append and the one I want to append is actually a UI image that is built by the name that is essentially
coming from any.
So we get the any make the right image.
Place it in the array.
So by the time my view is loaded my images array will have an array of UI images.
You could essentially do another thing as well.
And that is you could make all of these UI images.
You could essentially say here you I image name the dad is the name and then repeat the process for
all of these but I'd rather you know doing it like this because most likely you will read the strings
from a network not the actual image arrays.
And here is telling me that I don't know if this is going to result in an actual thing.
So I'm going to say no I know it already exists.
So we got that part taken care of.
So the next thing is I'm going to say my connection a number of items in sections is images array that
count and then I'm going to say my identifier is cell I.D. and my index fund is index.
But my cell is of the type my set.
And since it is like that then cell that I am view dot image can become images array object that index
part DOT rule.
So so far we've gotten in the cell the full roll and that one shows us an object of the type my cell
and that one should show us the correct image.
And by now I should be able to run the application and see the images appearing in the cells of the
collection view.
So once that is done the next step is to make sure that they are laid out properly and they each get
the height of their image.
So let's go ahead into taking care of that part.
So the design the layout for a collection view we need something that is called a UI collection view
layout and this the kind of class that must be subclass before it can be used.
So I'm going to go in here and say I have a new one called UI collection view layout this find that
the UI collection The View layout I'm going to call this one my custom layout my custom layout.
So this the UI collection view layout that we're subclasses and we will be using this to essentially
lay out the different cells in our collection view.
Unfortunately we have to do a lot of things before we can actually test this and make sure it is actually
happening.
So now the first thing I have to do is I have to go through my storyboard select my UI collection view
is a floor layout and say that is my custom layout making sure that from this point out the floor layout
for my collection view is based on my custom layout.
So now that that part is taking care of we're going to head into our view controller.
I'm going to go up in here before my view did load and I'm going to go ahead and say I have a variable
that is called my layout and my layout is actually of the type.
My custom layout now in my view though I'm going to go ahead and essentially implement that value I'm
going to say my layout is going to become self collection view from the collection view I'm going to
get the collection view layout just like what we had done before and this time I'm going to get it as
my custom layout so I make sure that my collection view layout is being interpreted as my custom layout.
So once we have our layout here in our view of the law then subsequently within our view controller
we have to talk about the custom layout itself what we should do in here.
There are a few things that you have to do in here which is actually quite important.
I'm first write them as as comments will be know what you have to do then I'm going to explain and quote
to each of them independently.
So the first thing that they have to do in here is we have to decide about a few things.
Number of columns in our particular situation the total content height.
What's that total content height that we're going to have.
And a very important thing that is called The Cell attributes that is essentially the attributes for
each particular cell.
What is the wheat and what's the height of that cell and more importantly where it presents itself to
sit.
All of these attributes we need a method that is called the prepare which is an essentially a built
in method of a UI collection view layout that the overriding once we're done with the preparation we
will have all the attributes that we need to do whatever we need to do with our different cells and
we have to lay them out and that's what we do with layout attributes for element in rectangle which
I will come back to it and I will explain how it works but it essentially is a way for us to find the
cell that is going to be presented in a certain section of a collection view and then we explain to
the to the software what are the attributes for this particular cell.
Now the last thing that we have to do in here is that as you are going through their preparation and
as we are changing the number of the elements and the height of them the over all height of the content
will change as well.
And for that we need another method that is called collection view content.
Size of course the size of it it represents both the width and height but we are not really interested
in the video part the fit the width whatever it is always set in our case but the height of it it changes
it's very similar to when we were doing the content size for a scroll view.
If you think of that sort.
We now kind of have the building blocks for what we are going to do.
And like I said unfortunately I can't run the application at any point in here because we have to do
all of these pieces of code to make sure everything works together and then we will be ready to to run
the application.
The first thing that we have to do in here is if you have to produce some sort of a connection between
this file my custom layout and our actual collection view controller and the images array we have to
find a way that for each image if we somehow produce the height of it and we offer it to our custom
layout and then do that using a delegation.
So up here I'm going to say I have a protocol on my political I'm going to call it custom cost layout
let's say delegate.
So a custom layout delegate with they have one function this one function I'm going to call it the height
for a cell and the cell that they want to get is at index part and that is obviously an index part either
returns a C G float simply because we need to return a value for the height of the set.
Let's recap this really quickly.
This delegation essentially allows us to find the height for each cell depending on the size of the
image from the array since there is going to be connected to our view controller.
I'm going to go in here and say the very first valuable that they have is a delegate and my delegate
is essentially a custom layout delegate which is this guy.
So now we have the delegate for my custom layout and we can use it in our view controller.
Let's go ahead and use do that that's what I'm gonna go to my correction of your controller in my view
did look after I made the my layout.
I'm gonna say my layout dot delegate becomes which is obviously after type custom layout delegate becomes
a self and since it is like that I have to go in here and say custom layout delegate is one of the protocols
that we conform to its custom layout delegate so my collection view now conforms to custom layout delegate
and my layout that delegate is using this file my view correction view controller as is delegation now
since we're using custom layout delegate we have to conform to it and use the functions of it which
is this is the only one that we need I'm going to put this at the very far bottom because that's the
last thing we're gonna be doing.
So here I'm going to write the comment for it in this function we should produce the height for each
set the height for each cell once it gets produced it has to go back to our custom layout and essentially
inform us of it in the preparation of what the attributes are for that cell and what is the overall
content height.
So let's jump in here.
Right on the top I'm going to say after I have the delegation I have a valuable card columns and that
is going to be a value of say three four now actually.
Could this make this a lot to value because we're not changing that.
That's something you could potentially connect to some sort of a settings section of your application.
This is a static value that's going to make three columns for applications collection view.
The next thing I'm going to do is I'm going to make a value in it.
And that's going to be a content.
Right.
And the content height is a C.G. float.
And that is by default to zero right at the very beginning we have no sales and the content height should
be set at zero.
Now in saying that we immediately need to take care of this one collection view content size we have
to return the size of it.
So I'm gonna go ahead and say return and the size of it is going to be a C G size that is built by a
vet on a height the height of it is very easy is the content height David if it is even easier.
It's essentially the collection view.
Dot boundaries and width.
So David's off the collection view is not going to change it is its height.
That might change and the height of it for now it is zero.
But as we go along in preparation we will have to change the height of the content.
Now I'm going to have one more valuable in here and that's valuable is essentially going to be the attributes
that we have for all of the cells.
So each cell is getting prepared.
We write down their attributes.
So I'm gonna go in here and say I have a variable and I'm going to call it all cells 82 hours and that's
going to become a very particular kind of array variable.
And that is your connection view layout attributes UI collection view and layout attributes.
So it's is a kind of object that maintains all attributes about a certain cell.
It maintains frame location content.
So on and so forth.
So once we have all the cell attributes we could essentially use them.
We don't have them yet.
And that's something I have to produce in my prepared and that's going to be our longest function.
But for now I can imagine that if I had them I could essentially going here and use them and let's see
how we will do we doing that.
And when I go in here and say for let's see any cell cheetah are these are the attributes of any cell
in all this cell 80 are within all of these if this situation happened if we had this situation where
any cell 80 are dot frame dot intersects vids rect if this cell that we are going to do is within this
rectangle it means this is that particular cell that we are looking for if that was the case we have
to find all of its attributes and the alphabets that we have to return is an array.
So I'm actually going to go ahead in here and say value about let's call it the return TTR which is
going to be again of the type of EU eye protection view lay out attributes.
So we have this array again and I'm going to say for any of the cells within all the cell attributes
if they are within the rectangle you are trying to draw right now.
Go ahead say return attributes dot append any cell attributes so add that to there and then obviously
finally at the end just returned.
Now I noticed a bit of a long process and a bit of a difficult one.
Once we ran the application and we could actually see how it works I'll come back and I will re-explain
this for you guys then actually going to make a note find myself re explain this spot because by then
we will be able to see things a little bit easier and we get a better sense of what's going on in prepare.
The first thing I'm going to say is that if we were to use the original design that we had created I
have it in here.
Each of these cells would need to have a it would need to have a height and would also need to have
a top left corner.
So they essentially need to know what's the frame for each of these cells we are trying to to make.
Now some things are easier than the other ones for instance if we know the vit of all of them is going
to be exactly the same thing.
And the height of you're going to infer it from this function.
The height for cell.
So we have to find the two origin x and y of the top left corner of them in here and prepare.
So I'm going to go ahead and say hello variable let's call it origin X which is a C G float and by default
a zero.
So let's say the origin x of each of the cells and as we go along we're gonna change it and we're going
to find new numbers.
The next thing is Origin y and this one is actually going to become a I'm writing it a slightly different
I'm writing it as an array and I'm going to go ahead and say here's how it is it is going to be a repeating
array of 0 and the count for it is columns.
So let's see what it means.
I'm writing the two of them in to a slightly different ways.
If we look at our simulator for the X I'm going to calculate it as I go along each time for the Y I'm
going to say there is an array there's got three values based on the number of the columns all three
of them are currently zero.
So it's essentially this location this one and this one the top left corner of each of the columns currently
is zero.
And as we go along I'm going to change that.
So for the idea of a zero in this array I calculate the value for this column for the idea of 1 I calculate
the value for the column in the middle and the last one for the column on the right.
So it is an array that maintains the vies for the first column the second column and the 10th column.
So that path is taken care of.
So the next thing I need to know is I need to know the vit of each of the columns.
So I'm going to go ahead and say let column wait.
It is a C G float of course.
And that becomes my correction view that boundaries that vit and I will divide that by the number of
columns and it helps if I get this C G float value of the.
So it doesn't give me an arrow so that's going to be the width of all of the columns because I need
to get the width of the collection view and divide that by the number of the columns that we have.
The error is because this I have to actually force unwrap it saying that the correction view actually
does exist.
And finally because in the origin y and in the origin X I have to calculate the value of them as we
go along.
It helps that I know which column I'm currently at because we go through the images of one two three
four five six seven eight nine we add them to each column one at a time.
So essentially we build the rows we make one road then we go on we make the next throw.
So on and so forth.
So for each of these I want to know which column I currently am going to go ahead and say I have something
called the value of an car and column car and column which is by default 0 because at the very beginning
at the left column.
So that's the basic stuff for my preparation.
The next thing is going through all the items of my collection view and then changing attributes and
writing it to my attributes array.
So here I'm going to go ahead in my prepare and say once I got this initial set things kind of for I
them in let's say from 0 to collection view from my collection view I'm going to get the number of items
in Section 0 because we only have one section for now I'm going to go through all the items in a numeric
way zero upwards.
So the first thing I'm going to calculate here is the origin X and the value of Origin X is this if
I in the very first column here it is zero.
Otherwise whatever the value was before plus column it then we end up here in the middle and then we
add another one and we end up for the last one.
So let's write it with a ternary if a statement I'm going to go ahead and say in some situation your
value becomes origin x plus the column of it.
So column that are there ways it becomes zero.
And my condition is this my condition is going to be if I them my shoelace columns are loans is not
zero.
So if we are not at the very first one then the value keeps adding to itself.
Otherwise the value is stays zero and that's going to be the value for the very first column.
Essentially if you are equal write this with a complete if a statement as about the next thing I want
to do is I want to buying the index spot in this current sell.
We are trying to find the attributes for it.
So I want to go ahead and say let this index part I call it index part of it.
Let's say I want to get an index smart for this particular place in this particular section.
So I'm going to say item and section section is obviously 0.
The item for it is the number of the item.
So I'm gonna go ahead and say item in item.
So I'm building an index spot not with a capital N with a lower case letter and I'm building an index
spot based on this current number.
In this kind section.
So once I have the index part I can go ahead and find something very important and that is this one
the height of that particular cell because if you remember what you were trying to find was the top
left corner value as well as the width as well as the height.
David we already know is the same thing for everyone which is the value is here kind of it's the origin
X we found for everyone the Y we still have to calculate and the height we still have to calculate.
So we're going to say let's find the value that is the cell height and then to say let's sell height
to be let's find a delegate unfunded delegate.
Let's find the height for sale at index spot which is this index.
Now if you remember this delegation is called in here and we still haven't done that part.
You still have to come back here and calculate the height for the cell but is getting us there we're
getting one step closer at least the next thing is producing the frame for this cell.
So I'm going to say let sell frame I'm going to say that's the CGI activates all the usual stuff.
Now you might be wondering why I haven't calculated the origin of y just yet.
I will explain that to you in a second.
For now we know the origin Y is an array that all of the values in it are 0 and 0 is the valid value
for us at the very beginning when item is 0 and I will experience I can the why I'm not doing that just
yet.
So I'm putting the origin y in here from the origin y.
We obviously have to get a specific item which is the current column which currently at the very beginning
is 0.
Then I'm going to go ahead and say the veto of it is kind of it's something that was very easy.
The height of it is cell height of course on the origin X is the value for the origin X which we have
calculated under is giving me a little error here.
It's saying use of extraneous and because all I have apparently made a mistake here the origin Y should
be a C G float R a not a float array.
So keep that in mind that I made the mistake in here and if you're following me please change that to
a C G float.
All right.
So now we have our cell frame and I have to actually change the value of Origin y as well.
So I'm going to go ahead and say origin y quadrant column in this current one becomes whatever is the
value of the origin y a gain within this client column plus cell height.
So let's see what this line means.
It means that get wherever we are in the origin y and add the cell height to it.
So basically in here if we are currently in this location where my mouse pointer is add as much as the
cell height to it and go to get the next one.
Now the reason I put this line after I made my frame is because I already have the frame for this cell
for this index fund and I am preparing it for the next one.
If we do this line before we make the frame it essentially pushes everything as much as one cell down
at the very beginning.
That's why I left origin wise calculation after I made my friend a better approach for this obviously
would be calculating both origin X and Y.
Before we get to this for loop but I don't want to make things overly complicated and the next thing
we have to do is we have to actually find what's the value for the current columns.
I'm going to go in here and say once you found the frame.
Go ahead and say crime column equals.
I'm going to use a conditional statement again I'm going to say based on some condition either it becomes
client column plus one.
So it has to add one tweet s or it becomes zero.
And the condition for it is this the condition for it is if client column is is smaller than columns
minus one.
So if we haven't reached the last column we keep adding to it.
Otherwise we had zero.
Let's see why that is.
So this column is column zero.
This one in the middle is obviously one on this one at the end is to the number of condoms are three.
So as long as we are below three minus one which is essentially two we keep adding.
Otherwise we headed to zero sum for a zero and one we keep adding the moment it becomes two then we
obviously head back to become zero and go back to the first column again.
So we now have our cell frame and we can add that as an attribute to our are all cell attributes.
I'm going to go in here and say now that we have that this go ahead and say let a TTR and that becomes
a new eye collection view lay out attributes.
And when I say that is for sale at this index spot so for sale at this index spot.
And what I want to do is I want to go ahead eventually say all say 80 yards dot append and the one I
want to append is the 82 yard but between these two I have to actually add the summer stuff to it.
Most importantly I have to somehow embed the sell that we made into this attribute.
So I'm going to go ahead and say that part that I really need to do is 82 yard dot frame becomes.
Now we could do one of the two things we could immediately add this guy to.
Say it because the sell frame and that's perfect fine find works properly.
But the problem is we won't even be able to see these little gaps between them.
So we kind of need to add the inset for it so I'm going to take the frame that we have and change it
with the inserts.
So I'm going to go ahead and say let's and I'm going to call it inset frame.
That becomes my current self frame that inset by and I'm going to insert it by both x and y by values
of 5 and 5 and I'm going to add to that frame to become the frame of my my art tribute when I add that
to my cell attributes.
Now before I close this that is one tiny tiny thing that we still have to do and that is this situation.
My value for content height is currently zero and if we keep this value at content height zero vividly
I still see these but you won't be able to scrawl it anymore simply because it's going to feel like
their value for the content height is always a static number of zero.
So I'm going to change that and get it going.
Yeah I'll say as we do this spot and as we make new frames and we have all the frames which is based
on the frame of the original cell and inserted by values of five and five then go ahead and say content
height becomes the value of this.
The maximum value between the current content height whatever that value might be and the value of inset
frame inset frame dot maximum y.
Now let me explain why we have to do this.
The reason we have to do this is this the content height is actually not calculated anywhere.
We are using it in here to find the content size and obviously we set it to zero at the very beginning
but then our content height essentially has to be the size of the highest column that we have.
So for instance in this current iteration this middle column the combination of the size of this cell
and this cell and this set all the way to the last one the total height of them should be our content
height.
Now the way we calculate it is this we are saying find the value of the size of this particular cell
find the height of that find the maximum value value of it which is essentially what it can reach at
the maximum value of the Y I'm put that as the content height.
Now you might be wondering what's the max value for let's say this wasn't here if you were only doing
it based on the maximum y value of the last object that we get because as we go through all the items
we get the last one in here and this example clearly shows what's going to happen because this picture
the one on the far right by them corner is actually shorter than the image in the middle or essentially
this column as the far right is shorter than the middle column somewhere before here we have reached
the higher value for the y of the content height but then here we are kind of shrinking it back.
That's why we said get the maximum value between the two of them if you have reached a higher one because
of one of the columns then keep it like that.
If we haven't then increases by whatever value is in here the max value is to account for the difference
between these different images.
So we got the attributes we added adhering to our all cell attributes and now we can go back in here.
The party was supposed to re-explain again.
I still remember that.
So the reason we need the layout attributes for elements is simply because you don't necessarily only
have cells in the sections you might have both cells and you might have supplementary views such as
the head their views or the footer views or any other kind of supplementary views and the rectangle
value here can understand which part of the collection view you are trying to lay out at that particular
moment.
So if the rectangle is the body of the cells then what we want to do is we want to return the values
from the all the cells attributes which we have built in here during our preparation.
If it is not in this case we are not doing anything else.
If you wanted you could actually have another you know array of attributes that was relevant to the
values of the supplementary views.
That's why we had to do this thing in here.
We had to return the attribute for any of the cells but that depends on the cells that we have placed
into the array before and also there in the collection view we currently are at.
So almost everything is ready.
The last part we have to do is calculating this value the cell height which has to be calculated somewhere
else essentially depending on something else.
So let's call ahead to a collection view controller.
And here we produce the height for each of the cells and let's see how we're going to do that to do
that.
I'm going to go ahead and say let's first get the image.
We are trying to show in this particular cell I'm going to say let oration not image that's going to
become my images array object at index path dot item.
So we find the original image.
Then the next thing you have to do is we could just simply go ahead and say let's get this images height
but that height is not necessarily proportional to the size of our columns.
So we have to get its height and we have to make it proportional to the current Vit.
So to do that I'm going to go ahead and say let's get the vet the width of any of them which is very
similar to what we did in the other fine.
I'm going to say sell off dot collection view from the collection view I'm going to get the boundaries
from the boundaries.
I'm going to get the vit of course and I'm going to divide that by the number of the columns and the
number of the columns I have to get it from this object.
My custom layout which I've called it my layout so I'm going to go ahead and say my layout dot columns.
So how many columns are there.
And it really helps if I convert this to a C G float so C G float of this value.
Let me see if I can get all of it in one line.
So yes.
So I'm going to get my corner of it which is the total collection view of it divided by the number of
the columns which returns the same kind of weight as we have in the in the custom layout.
Now do they have that I can get these values.
I can say let this get the vit ratio to become column it divided my original image dot size dot Vit.
So that's the ratio that we have between the current weight and the old width essentially let new height
to become original image that size that height.
I'm going to get that value multiplied by width ratio.
So now I have the new height which is exactly what we need to return.
So new height we have done something like this.
I remember many many sections.
That was when we were trying to fit so many images within a scroll view.
This is kind of a similar situation.
We have an image and we want to make sure that that image actually fits itself within the size that
we have in this particular column.
So if it all goes well we should be able to run this application now and we should be able to get something
quite similar identical to what I've been showing you all through this less than this very very long
lesson with so much to doing it.
So let's see if that's going to happen.
And here is exactly what you were expecting to see.
We have all the columns we have the number of the items that we had as different index parts in here.
And obviously the total height is calculated based on the tallest column that we have so that's about
it for this lesson.
It's been a very very long lesson.
If you run into any issues or if you felt something is still not quite clear Drop me a line or write
in the discussion boards and I will get back to you with more clarification for it.
So let's keep it up to here.
Let's move on to our next lesson.