iOS teaches you to easily create waterfall flow layout

Source: Internet
Author: User

Objective:

Before I write this article, I congratulate myself that my GitHub is finally here. This is also my GitHub first code, the following article code can be in the demo clone or download. You are welcome to give your opinion. Do not hesitate to give your star a good written opinion.

Waterfall Flow

First of all, what is waterfall flow?

Waterfall flow, also known as Waterfall flow layout. is a more popular Site page layout, visually displayed as a jagged multi-column layout, as the page scroll bar scroll down, this layout will continue to load the data block and attached to the current trailer. The earliest use of this layout of the site is Pinterest, gradually popular in the country.

Uicollectionview

We know that Uicollectionview is another very, very, very good UI control that Apple has introduced to UITableView, in addition to the UITableView cache pool, the reuse mechanism, you can build your own item (TableView in the cell , the display layout of the item in CollectionView, as long as you pass a layout property to it, he will be able to display the item as you wish.

Uicollectionviewlayout

Here I use the custom class Jrwaterfalllayout to inherit Uicollectionviewlayout to write the waterfall flow layout.

    • 4 methods that need to be implemented manually

Method Description
– (void) preparelayout The method is called when the CollectionView is first laid out and when the layout is invalidated, and it is important to note that the subclass remembers to call Super
-(nsarray<uicollectionviewlayoutattributes *> *) Layoutattributesforelementsinrect: (CGRect) rect Returns an array of layout properties for all elements within a rect range
– (Uicollectionviewlayoutattributes *) Layoutattributesforitematindexpath: (Nsindexpath *) IndexPath Returns the layout properties of an element on a indexpath position
– (Cgsize) collectionviewcontentsize Returns the scroll range of the CollectionView

Note: Because the Layoutattributesforelementsinrect method calls are very frequent, the array of layout properties should only be computed once and not recalculated every time the method is called

Agent

Provides an interface to modify some of the waterfall flow layout parameters, such as the number of columns displayed, column spacing, leading, margin (uiedgeinsets), if the agent does not implement the method, then use the default parameters: The most important thing is the height of the item!! Because the height of each picture (item) is determined by the aspect ratio of the picture and the Itemwidth. So itemheight must be determined by the agent. Here are a few proxy methods:

Proxy Method Description
@required
– (CGFloat) Waterfalllayout: (Jrwaterfalllayout *) waterfalllayout Heightforitematindex: (nsuinteger) Index width: ( CGFloat) Width Returns the height of item under the index position
@optional
– (Nsuinteger) Columncountofwaterfalllayout: (Jrwaterfalllayout *) waterfalllayout Returns the number of columns displayed by the waterfall stream
– (CGFloat) Rowmarginofwaterfalllayout: (Jrwaterfalllayout *) waterfalllayout Return line Spacing
– (CGFloat) Columnmarginofwaterfalllayout: (Jrwaterfalllayout *) waterfalllayout return column Spacing
– (Uiedgeinsets) Edgeinsetsofwaterfalllayout: (Jrwaterfalllayout *) waterfalllayout return Edge Spacing

Note: Due to the above, Layoutattributesforelementsinrect method calls are very frequent, so proxy methods are bound to be frequently called. But not all proxy methods are @required, so when calling @optional's proxy method, you need the following code to determine whether the proxy responds to the selector each time, in case the agent does not implement the method, and the call causes the program to crash

If ( [self. Delegate

Respondstoselector:@selector(columncountofwaterfalllayout:)] {

_columncount = [self. Delegate columncountofwaterfalllayout:self];

} Else {

_columncount = jrdefaultcolumncount;

}

Every time this judgment is obviously inefficient, we can make a sexual judgment in the Preparelayout method, and then store it with a flags structure, then next time we call the flag to judge. As follows:

struct { //record agent responds to selector

BOOL didrespondcolumncount:1; The 1 here is stored in 1 bytes

BOOL Didrespondcolumnmargin:1;

BOOL Didrespondrowmargin:1;

BOOL didrespondedgeinsets:1;

} _delegateflags;-

(void) setupdelegateflags{

_delegateflags.didrespondcolumncount = [Self.delegate respondstoselector: @selector (columncountofwaterfalllayout:) ];

_delegateflags.didrespondcolumnmargin = [Self.delegate respondstoselector: @selector (columnmarginofwaterfalllayout :)];

_delegateflags.didrespondrowmargin = [Self.delegate respondstoselector: @selector (rowmarginofwaterfalllayout:)];

_delegateflags.didrespondedgeinsets = [Self.delegate respondstoselector: @selector (edgeinsetsofwaterfalllayout:)];

}

So the next time you call the method, it's going to be a little more elegant.

_columncount = _delegateflags.didrespondcolumncount? [Self.delegate columncountofwaterfalllayout:self]: jrdefaultcolumncount;

The most important part of the waterfall flow layout is to find the location of the item. Exactly what the Layoutattributesforitematindexpath method is going to do. Let's start with the idea of finding this item position.

Waterfall Flow Layout Ideas

Here I need to use a total of 2 variable array and a assign property, one to record the height of each column, one to record all itemattributes. Assign is used to record the height of the column with the highest height

/** itemattributes Array */

@Property (nonatomic, strong) nsmutablearray *attrsarray;

/** array of heights per column */

@Property (nonatomic, strong) nsmutablearray *columnheights ;

/** Maximum y value */

Property (nonatomic, assign) cgfloat maxy;

In the Preparelayout method, the above 2 arrays are to be emptied, because the network request of new data to, CollectionView to re-layout if not empty, continue to add things inside, will lead to the layout of the item is all messed up.

The next thing to deal with is how each item in the Layoutattributesforitematindexpath method is laid out. The idea is simple.

    • Create a Uicollectionviewlayoutattributes object

    • Calculates the width of the item according to several parameters, such as width and line spacing of the CollectionView

    • Find the column number of the shortest column

    • Calculates the X-value, y-value of item according to the column number, asking the agent to get the height of item

    • Set the Frame property of a Uicollectionviewlayoutattributes object

    • Returns the Uicollectionviewlayoutattributes object

The main problem is how to calculate x, y, width, height. Look at the picture and talk.

Detailed calculation steps can be seen in the demo.

At last

Theoretically, as long as you have strong enough algorithmic computing power, any display layout can be written out. The collectionviewlayout is not just a waterfall stream!

iOS teaches you to easily create waterfall flow layout

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.