UICollectionView左對齊流水佈局、右對齊流水佈局

 

    在平時使用的app中會常常碰到一些規格選擇,篩選,標籤等頁面,這些頁面的佈局展現一般是左對齊流水佈局。
實現相似這樣的左對齊流水佈局有多種方式,若是選項少的話能夠直接用UIButton實現。如今咱們有一種比較簡單的方式能夠實現這個目的。
就是對UICollectionView稍加改動,就能輕鬆實現。
下面介紹一下具體實現的方法。git

    經過 ZFFlowLayout類能夠建立一個默認距離的佈局實例,也能夠建立一個自定義距離的佈局實例。github

#import <UIKit/UICollectionViewFlowLayout.h>
#import "ZFFlowLayoutMacro.h"
#import "ZFFlowLayoutProtocol.h"

//流水佈局類型
typedef enum : NSUInteger {
    FlowLayoutType_leftAlign,
    FlowLayoutType_rightAlign,
} FlowLayoutType;

@interface ZFFlowLayout : NSObject

/*!
 *  @author zhoufei
 *
 *  @brief 根據傳入不一樣的流失佈局類型獲取不一樣的佈局實例
 *  @param flowLayoutType 流水佈局類型
 *  @return 佈局實例
 */
+ (UICollectionViewFlowLayout *)flowLayoutWithFlowLayoutType:(FlowLayoutType)flowLayoutType;


/*!
 *  @author zhoufei
 *
 *  @brief 自定義佈局實例:根據傳入不一樣的流失佈局類型,item距離四周距離,section距離四周距離 自定義佈局實例
 *  @param flowLayoutType 流水佈局類型
 *  @param itemEdgeInsets 第一個item距離四周的距離
 *  @param sectionEdgeInsets section距離四周的距離
 *  @return 佈局實例
 */
+ (UICollectionViewFlowLayout<ZFFlowLayoutProtocol> *)flowLayoutWithFlowLayoutType:(FlowLayoutType)flowLayoutType
                                                                    ItemEdgeInsets:(FlowLayoutItemEdgeInsets)itemEdgeInsets
                                                                 sectionEdgeInsets:(FlowLayoutSectionEdgeInsets)sectionEdgeInsets;

調用以下方法能夠根據想要建立的佈局類型,生成一個佈局實現。數組

+ (UICollectionViewFlowLayout *)flowLayoutWithFlowLayoutType:(FlowLayoutType)flowLayoutType;

調用以下方法能夠根據想要建立的佈局類型和第一個item距離四周的距離與section距離四周的距離,生成一個自定義的佈局實現。app

+ (UICollectionViewFlowLayout<ZFFlowLayoutProtocol> *)flowLayoutWithFlowLayoutType:(FlowLayoutType)flowLayoutType
                                                                    ItemEdgeInsets:(FlowLayoutItemEdgeInsets)itemEdgeInsets
                                                                 sectionEdgeInsets:(FlowLayoutSectionEdgeInsets)sectionEdgeInsets;

在第二個方法中使用到了自定義的枚舉和結構體,它們的具體實現以下:
#ifndef ZFFlowLayoutMacro_h
#define ZFFlowLayoutMacro_h

/*!** 
 左對齊佈局時:左上角第一個item 距離四周的距離
 右對齊佈局時:右上角第一個item 距離四周的距離
  ***/
typedef struct FlowLayoutItemEdgeInsets {
    CGFloat top, left, bottom, right;  // specify amount to inset (positive) for each of the edges. values can be negative to 'outset'
} FlowLayoutItemEdgeInsets;

/*!** item所屬的組section 距離四周的距離 ***/
typedef struct FlowLayoutSectionEdgeInsets {
    CGFloat top, left, bottom, right;  // specify amount to inset (positive) for each of the edges. values can be negative to 'outset'
} FlowLayoutSectionEdgeInsets;

#endif /* ZFFlowLayoutMacro_h */

結構體中值得具體含義已經在註釋中寫出,這裏就不在講了。佈局

下面講一下最核心的類 LeftAlignedFlowLayout類spa

由於這個類代碼略有點長,這裏就這貼出主要的邏輯代碼:代理

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSMutableArray* attributes = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
    
    NSMutableArray * subArray = [LayoutAttributeTools groupTheSameLineItems:attributes];

    [self leftAlign_updateItemAttributeInSigleLine:subArray];
 
    return attributes;
}

/*!
 *  @author zhoufei
 *
 *  @brief 更新每一個元素的位置
 *  @param groupArray 歸併後的結果數組
 */
- (void)leftAlign_updateItemAttributeInSigleLine:(NSMutableArray * )groupArray{
    
    NSMutableArray * modelArray = [NSMutableArray array];
    
    for (NSArray * array  in groupArray) {
        
        NSInteger count = array.count;
        
        if (!count) {
            continue;
        }
        
        for (int i = 0; i<count; i++) {
            UICollectionViewLayoutAttributes *attrOne = array[i];
            [modelArray addObject:[Attribute AttributeWithIndex:i width:attrOne.size.width]];
            
        }
        
        CGFloat leftWith = 0;
        
        for (int i=0; i<count; i++) {
            
            UICollectionViewLayoutAttributes *attr = [array objectAtIndex:i];
            
            NSPredicate *predice =[NSPredicate predicateWithFormat:@"index < %d",i];
            NSArray * resultArray = [modelArray filteredArrayUsingPredicate:predice];
            NSNumber * number = [resultArray valueForKeyPath:@"@sum.width"];
            
            leftWith = self.leftMargin+self.itemMargin*i+number.doubleValue;
            
            CGRect frame = attr.frame;
            frame.origin.x = leftWith;
            attr.frame = frame;
            
        }
        [modelArray removeAllObjects];
    }
    
}

上面這個方法
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
是父類 UICollectionViewFlowLayout的代理方法,在這個方法中能夠拿到當前屏幕中顯示的全部 UICollectionViewCell的佈局實現,咱們對
UICollectionViewCell的佈局修改也就是在這個方法中。
首先經過方法 [LayoutAttributeTools groupTheSameLineItems:attributes];對屏幕中顯示的每一行 UICollectionViewCell 進行分組。這樣分組以後邏輯比較清晰。只須要設置每一行UICollectionViewCell的新佈局實例,剩餘的也都是有每一行組成的。直接來個循環就搞定了。
方法 [self leftAlign_updateItemAttributeInSigleLine:subArray];就是對分組後的UICollectionViewCell進行逐行更新佈局實例對象的值。具體實現已經在代碼中給出了。

Demo地址:https://github.com/zhfei/ZFFlowLayout

  歡迎star。code

  若是發現不對的地方歡迎批評和指正。orm

相關文章
相關標籤/搜索