You can arrange items in your collection views using a concrete(具体的) layout object, the UICollectionViewFlowLayout class. The flow layout implements a line-based breaking layout, which means that the layout object places cells on a linear path and fits as many cells along that line as it can. When the layout object runs out of room on the current line, it creates a new line and continues the layout process there. Figure 3-1 shows what this looks like for a flow layout that scrolls vertically. In this case, lines are laid out horizontally with each new line positioned below the previous line. The cells in a single section can be optionally surrounded with section header and section footer views.
You can use the flow layout to implement grids(网格), but you can also use it for much more. The idea of a linear layout can be applied to many different designs. For example, rather than having a grid of items, you can adjust the spacing to create a single line of items along the scrolling dimension(尺寸). Items can also be different sizes, which yields(让) something more asymmetrical(不对称的) than a traditional grid but that still has a linear flow to it. There are many possibilities.
You can configure the flow layout either programmatically or using Interface Builder in Xcode. The steps for configuring the flow layout are as follows:
Create a flow layout object and assign it to your collection view.
Configure the width and height of cells.
Set the spacing options (as needed) for the lines and items.
If you want section headers or section footers, specify their size.
Set the scroll direction for the layout.
Important: At a minimum, you must specify the width and height of cells. If you don’t, your items are assigned a width and height of 0 and will never be visible.
Customizing the Flow Layout Attributes
The flow layout object exposes(揭露) several properties for configuring the appearance of your content. When set, these properties are applied to all items equally in the layout. For example, setting the cell size using the itemSize property of the flow layout object causes all cells to have the same size.
If you want to vary the spacing or size of items dynamically, you can do so using the methods of the UICollectionViewDelegateFlowLayout protocol. You implement these methods on the same delegate object you assigned to the collection view itself. If a given method exists, the flow layout object calls that method instead of using the fixed value it has. Your implementation must then return appropriate values for all of the items in the collection view.
Specifying the Size of Items in the Flow Layout
If all of the items in the collection view are the same size, assign the appropriate width and height values to the itemSize property of the flow layout object. (Always specify the size of items in points.) This is the fastest way to configure the layout object for content whose size does not vary.
If you want to specify different sizes for your cells, you must implement the collectionView:layout:sizeForItemAtIndexPath: method on the collection view delegate. You can use the provided index path information to return the size of the corresponding(相符的) item. During layout, the flow layout object centers items vertically on the same line, as shown in Figure 3-2. The overall(总体的) height or width of the line is then determined by the largest item in that dimension.
Note: When you specify different sizes for cells, the number of items on a single line can vary from line to line.
Specifying the Space Between Items and Lines
Using the flow layout, you can specify the minimum spacing between items on the same line and the minimum spacing between successive lines. Keep in mind that the spacing you provide is only the minimum spacing. Because of how it lays out content, the flow layout object may increase the spacing between items to a value greater than the one you specified. The layout object may similarly increase the actual line-spacing when the items being laid out are different sizes.
During layout, the flow layout object adds items to the current line until there is not enough space left to fit an entire item. If the line is just big enough to fit an integral(内置的,必须的) number of items with no extra space, then the space between the items would be equal to the minimum spacing. If there is extra space at the end of the line, the layout object increases the interitem spacing until the items fit evenly within the line boundaries, as shown in Figure 3-3. Increasing the spacing improves the overall look of the items and prevents large gaps at the end of each line.
For interline spacing, the flow layout object uses the same technique that it does for inter-item spacing. If all items are the same size, the flow layout is able to respect the minimum line spacing value absolutely and all items in one line appear to be spaced evenly from the items in the next line. If the items are of different sizes, the actual spacing between individual items can vary.
Figure 3-4 demonstrates what happens with the minimum line spacing when items are of different sizes. With differently sized items, the flow layout object picks the item from each line whose dimension in the scrolling direction is the largest. For example, in a vertically scrolling layout, it looks for the item in each line with the greatest height. It then sets the spacing between those items to the minimum value. If the items are on different parts of the line, as shown in the figure, the actual line spacing appears to be greater than the minimum.
As with other flow layout attributes, you can use fixed spacing values or vary the values dynamically. Line and item spacing is handled on a section-by-section basis. Thus, the line and interitem spacing is the same for all of the items in a given section but may vary between sections. You set the spacing statically using the minimumLineSpacing and minimumInteritemSpacing properties of the flow layout object or using the collectionView:layout:minimumLineSpacingForSectionAtIndex: and collectionView:layout:minimumInteritemSpacingForSectionAtIndex:methods of your collection view delegate.
Using Section Insets to Tweak(轻微调整) the Margins of Your Content
Section insets are a way to adjust the space available for laying out cells. You can use insets to insert space after a section’s header view and before its footer view. You can also use insets to insert space around the sides of the content. Figure 3-5 demonstrates how insets affect some content in a vertically scrolling flow layout.
Because insets reduce the amount of space available for laying out cells, you can use them to limit the number of cells in a given line. Specifying insets in the nonscrolling direction is one way to constrict the space for each line. If you combine that information with an appropriate cell size, you can control the number of cells on each line.
Knowing When to Subclass the Flow Layout
Although you can use the flow layout very effectively without subclassing, there are still times when you might need to subclass to get the behavior you need. Table 3-1 lists some of the scenarios(设想的情况) for which subclassing UICollectionViewFlowLayout is necessary to achieve the desired effect.
There are also instances in which the right thing to do is to create a custom layout from scratch. Before you decide to do this, take the time to consider whether or not it is really necessary. The flow layout provides a lot of customizable behavior that is appropriate for many different kinds of layouts, and because it is provided to you, it is easy to use and contains numerous optimizations to make it efficient. However, all this is not to say that you should never create a custom layout, because there are circumstances in which doing so make absolute sense. The flow layout limits the scroll direction to one direction, so if your layout contains content that stretches farther than the bounds of the screen in both directions, a custom layout makes more sense to implement. Creating a custom layout is the right decision if your layout is not a grid or a line-based breaking layout, as described above, or if the items within your layout move so frequently that subclassing the flow layout is more compicated than creating your own.
For more on creating a custom layout, see Creating Custom Layouts.