zoukankan      html  css  js  c++  java
  • WaterflowLayout 瀑布流布局

    Model Data

    @interface Shop : NSObject
    @property (nonatomic, assign) CGFloat w;
    @property (nonatomic, assign) CGFloat h;
    @property (nonatomic, copy) NSString *img;
    @property (nonatomic, copy) NSString *price;
    @end

    define cell

    @class Shop;
    @interface ShopCell : UICollectionViewCell
    @property (nonatomic, strong) Shop *shop;
    @end
    
    #import "ShopCell.h"
    #import "Shop.h"
    #import "UIImageView+WebCache.h"
    
    @interface ShopCell()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    @property (weak, nonatomic) IBOutlet UILabel *priceLabel;
    @end
    
    @implementation ShopCell
    
    - (void)setShop:(Shop *)shop
    {
        _shop = shop;
    
        // 1.图片
        [self.imageView sd_setImageWithURL:[NSURL URLWithString:shop.img] placeholderImage:[UIImage imageNamed:@"loading"]];
    
        // 2.价格
        self.priceLabel.text = shop.price;
    }
    @end

    xib 
    这里写图片描述

    WaterflowLayout 瀑布流布局

    @class WaterflowLayout;
    
    @protocol WaterflowLayoutDelegate <NSObject>
    - (CGFloat)waterflowLayout:(WaterflowLayout *)waterflowLayout heightForWidth:(CGFloat)width atIndexPath:(NSIndexPath *)indexPath;
    @end
    
    @interface WaterflowLayout : UICollectionViewLayout
    @property (nonatomic, assign) UIEdgeInsets sectionInset;
    /** 每一列之间的间距 */
    @property (nonatomic, assign) CGFloat columnMargin;
    /** 每一行之间的间距 */
    @property (nonatomic, assign) CGFloat rowMargin;
    /** 显示多少列 */
    @property (nonatomic, assign) int columnsCount;
    
    @property (nonatomic, weak) id<WaterflowLayoutDelegate> delegate;
    
    @end
    
    @interface WaterflowLayout();
    /** 这个字典用来存储每一列最大的Y值(每一列的高度) */
    @property (nonatomic, strong) NSMutableDictionary *maxYDict;
    
    /** 存放所有的布局属性 */
    @property (nonatomic, strong) NSMutableArray *attrsArray;
    @end
    
    @implementation WaterflowLayout
    
    - (NSMutableDictionary *)maxYDict
    {
        if (!_maxYDict) {
            self.maxYDict = [[NSMutableDictionary alloc] init];
        }
        return _maxYDict;
    }
    
    - (NSMutableArray *)attrsArray
    {
        if (!_attrsArray) {
            self.attrsArray = [[NSMutableArray alloc] init];
        }
        return _attrsArray;
    }
    
    - (instancetype)init
    {
        if (self = [super init]) {
            self.columnMargin = 10;
            self.rowMargin = 10;
            self.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
            self.columnsCount = 3;
        }
        return self;
    }
    
    - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
    {
        return YES;
    }
    
    /**
     *  每次布局之前的准备
     */
    - (void)prepareLayout
    {
        [super prepareLayout];
    
        // 1.清空最大的Y值
        for (int i = 0; i<self.columnsCount; i++) {
            NSString *column = [NSString stringWithFormat:@"%d", i];
            self.maxYDict[column] = @(self.sectionInset.top);
        }
    
        // 2.计算所有cell的属性
        [self.attrsArray removeAllObjects];
        NSInteger count = [self.collectionView numberOfItemsInSection:0];
        for (int i = 0; i<count; i++) {
            UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
            [self.attrsArray addObject:attrs];
        }
    }
    
    /**
     *  返回所有的尺寸
     */
    - (CGSize)collectionViewContentSize
    {
        __block NSString *maxColumn = @"0";
        [self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL *stop) {
            if ([maxY floatValue] > [self.maxYDict[maxColumn] floatValue]) {
                maxColumn = column;
            }
        }];
        return CGSizeMake(0, [self.maxYDict[maxColumn] floatValue] + self.sectionInset.bottom);
    }
    
    /**
     *  返回indexPath这个位置Item的布局属性
     */
    - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        // 假设最短的那一列的第0列
        __block NSString *minColumn = @"0";
        // 找出最短的那一列
        [self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL *stop) {
            if ([maxY floatValue] < [self.maxYDict[minColumn] floatValue]) {
                minColumn = column;
            }
        }];
    
        // 计算尺寸
        CGFloat width = (self.collectionView.frame.size.width - self.sectionInset.left - self.sectionInset.right - (self.columnsCount - 1) * self.columnMargin)/self.columnsCount;
        CGFloat height = [self.delegate waterflowLayout:self heightForWidth:width atIndexPath:indexPath];
    
        // 计算位置
        CGFloat x = self.sectionInset.left + (width + self.columnMargin) * [minColumn intValue];
        CGFloat y = [self.maxYDict[minColumn] floatValue] + self.rowMargin;
    
        // 更新这一列的最大Y值
        self.maxYDict[minColumn] = @(y + height);
    
        // 创建属性
        UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
        attrs.frame = CGRectMake(x, y, width, height);
        return attrs;
    }
    
    /**
     *  返回rect范围内的布局属性
     */
    - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
    {
        return self.attrsArray;
    }
    
    @end
    

    控制器 ViewController

    #import "ViewController.h"
    #import "WaterflowLayout.h"
    #import "MJExtension.h"
    #import "Shop.h"
    #import "ShopCell.h"
    #import "MJRefresh.h"
    
    @interface ViewController () <UICollectionViewDataSource, UICollectionViewDelegate, WaterflowLayoutDelegate>
    @property (nonatomic, weak) UICollectionView *collectionView;
    @property (nonatomic, strong) NSMutableArray *shops;
    @end
    
    @implementation ViewController
    
    - (NSMutableArray *)shops
    {
        if (_shops == nil) {
            self.shops = [NSMutableArray array];
        }
        return _shops;
    }
    
    static NSString *const ID = @"shop";
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        // 1.初始化数据
        NSArray *shopArray = [Shop objectArrayWithFilename:@"1.plist"];
        [self.shops addObjectsFromArray:shopArray];
    
    
        WaterflowLayout *layout = [[WaterflowLayout alloc] init];
        layout.delegate = self;
    //    layout.sectionInset = UIEdgeInsetsMake(100, 20, 40, 30);
    //    layout.columnMargin = 20;
    //    layout.rowMargin = 30;
    //    layout.columnsCount = 4;
    
        // 2.创建UICollectionView
        UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
        collectionView.backgroundColor = [UIColor whiteColor];
        collectionView.dataSource = self;
        collectionView.delegate = self;
        [collectionView registerNib:[UINib nibWithNibName:@"ShopCell" bundle:nil] forCellWithReuseIdentifier:ID];
        [self.view addSubview:collectionView];
        self.collectionView = collectionView;
    
        // 3.增加刷新控件
        [self.collectionView addFooterWithTarget:self action:@selector(loadMoreShops)];
    }
    
    - (void)loadMoreShops
    {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSArray *shopArray = [Shop objectArrayWithFilename:@"1.plist"];
            [self.shops addObjectsFromArray:shopArray];
            [self.collectionView reloadData];
            [self.collectionView footerEndRefreshing];
        });
    }
    
    #pragma mark - <WaterflowLayoutDelegate>
    - (CGFloat)waterflowLayout:(WaterflowLayout *)waterflowLayout heightForWidth:(CGFloat)width atIndexPath:(NSIndexPath *)indexPath
    {
        Shop *shop = self.shops[indexPath.item];
        return shop.h / shop.w * width;
    }
    
    #pragma mark - <UICollectionViewDataSource>
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
    {
        return self.shops.count;
    }
    
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        ShopCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath];
        cell.shop = self.shops[indexPath.item];
        return cell;
    }
    
    @end

    瀑布流效果图

    这里写图片描述这里写图片描述

  • 相关阅读:
    CodeForces 660D Number of Parallelograms
    【POJ 1082】 Calendar Game
    【POJ 2352】 Stars
    【POJ 2481】 Cows
    【POJ 1733】 Parity Game
    【NOI 2002】 银河英雄传说
    【NOI 2015】 程序自动分析
    【POJ 1704】 Georgia and Bob
    【HDU 2176】 取(m堆)石子游戏
    【SDOI 2016】 排列计数
  • 原文地址:https://www.cnblogs.com/crash-wu/p/4923626.html
Copyright © 2011-2022 走看看