CollectionView的詳細(xì)使用(四)

本人小白,歡迎各位大佬補(bǔ)充指點(diǎn)

自定義布局-瀑布流

實(shí)現(xiàn)瀑布流常見(jiàn)的3中方案:
1.view上面添加一個(gè)scrollView,接著在添加3列tableView,分別禁止tableView的滾動(dòng)
2.view上面添加一個(gè)scrollView,在一個(gè)一個(gè)往scrollView上面添加
3.用UIConllectionView
分析可得:瀑布流總是找最短的那個(gè)添加,因此不是流水布局,那么自定義布局就要繼承自根布局

控制器代碼如下:

#import "ZHWaterLayout.h"
#import "ViewController3.h"
#import "ZHShopViewCell.h"
#import "MJRefresh.h"
#import "ZHShop.h"
#import "MJExtension.h"
@interface ViewController3 ()<UICollectionViewDataSource,ZHWaterLayoutDelegate>
@property (nonatomic,strong) NSMutableArray *dataArray;
@property (nonatomic,weak) UICollectionView *collectionView;
@end
static NSString * const cellID = @"shopcell";

@implementation ViewController3
-(NSMutableArray *)dataArray{
    if (_dataArray == nil) {
        _dataArray = [NSMutableArray array];
    }
    return _dataArray ;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupLayout];
    [self setupRefresh];
}
-(void)setupRefresh{
    self.collectionView.header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(newData)];
    [self.collectionView.header beginRefreshing];
    self.collectionView.footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(moreData)];
    self.collectionView.footer.hidden = YES;
}
-(void)newData{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSArray *aray = [ZHShop objectArrayWithFilename:@"112.plist"];
        [self.dataArray removeAllObjects];
        [self.dataArray addObjectsFromArray:aray];
        [self.collectionView reloadData];
        [self.collectionView.header endRefreshing];
    });
   
}
-(void)moreData{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSArray *aray = [ZHShop objectArrayWithFilename:@"112.plist"];
        [self.dataArray addObjectsFromArray:aray];
        [self.collectionView reloadData];
        [self.collectionView.footer endRefreshing];
    });
    
}
-(void)setupLayout{
    ZHWaterLayout *layout = [[ZHWaterLayout alloc] init];
    layout.delegate = self;
    UICollectionView *collection = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
    //只能注冊(cè)
    [collection registerNib:[UINib nibWithNibName:@"ZHShopViewCell" bundle:nil] forCellWithReuseIdentifier:cellID];
    collection.backgroundColor = [UIColor whiteColor];
    collection.dataSource = self;
    self.collectionView = collection;
    [self.view addSubview:collection];
}

#pragma mark - UICollectionViewDataSource
//必須實(shí)現(xiàn)@required:
//每個(gè)section里面有多少個(gè)item
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    self.collectionView.footer.hidden = self.dataArray.count == 0;
    return self.dataArray.count;
}

//每個(gè)cell
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    ZHShopViewCell *item = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
    item.shop = self.dataArray[indexPath.item];
    return item;
}
#pragma mark - ZHWaterLayoutDelegate
-(CGFloat)waterLayout:(ZHWaterLayout *)waterLayout heightForItemAtIndex:(NSInteger )index andItemWidth:(CGFloat)itemWidth{
    ZHShop *shop = self.dataArray[index];
    return itemWidth * shop.h/shop.w;
}
-(NSInteger)columCountWaterLayout:(ZHWaterLayout *)waterLayout{
    return 4;
}
-(CGFloat)columMarginWaterLayout:(ZHWaterLayout *)waterLayout{
    return 10;
}
-(CGFloat)rowMarginWaterLayout:(ZHWaterLayout *)waterLayout{
    return 10;
}
-(UIEdgeInsets)edgeInsetsWaterLayout:(ZHWaterLayout *)waterLayout{
    return UIEdgeInsetsMake(10, 10, 10, 10);
}
@end

自定義xib的cell代碼如下:

#import <UIKit/UIKit.h>
@class ZHShop;
@interface ZHShopViewCell : UICollectionViewCell
@property (nonatomic, strong) ZHShop *shop;
@end
#import "ZHShopViewCell.h"
#import "ZHShop.h"
#import "UIImageView+WebCache.h"
@interface ZHShopViewCell()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UILabel *priceLabel;

@end
@implementation ZHShopViewCell

- (void)setShop:(ZHShop *)shop
{
    _shop = shop;
    // 1.圖片
    [self.imageView sd_setImageWithURL:[NSURL URLWithString:shop.img] placeholderImage:[UIImage imageNamed:@"loading"]];
    // 2.價(jià)格
    self.priceLabel.text = shop.price;
}
@end

模型ZHShop如下:

#import <UIKit/UIKit.h>

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

自定義布局ZHWaterLayout如下:

#import <UIKit/UIKit.h>
@class ZHWaterLayout;
//自定義協(xié)議
@protocol ZHWaterLayoutDelegate<NSObject>
@required
/**
 返回item的高度
 */
-(CGFloat)waterLayout:(ZHWaterLayout *)waterLayout heightForItemAtIndex:(NSInteger )index andItemWidth:(CGFloat)itemWidth;
@optional
/**
 有多少列
 */
-(NSInteger)columCountWaterLayout:(ZHWaterLayout *)waterLayout;
/**
列邊距
 */
-(CGFloat)columMarginWaterLayout:(ZHWaterLayout *)waterLayout;
/**
行間距
 */
-(CGFloat)rowMarginWaterLayout:(ZHWaterLayout *)waterLayout;
/**
 內(nèi)邊距
 */
-(UIEdgeInsets )edgeInsetsWaterLayout:(ZHWaterLayout *)waterLayout;
@end
@interface ZHWaterLayout : UICollectionViewLayout
@property (nonatomic,weak) id<ZHWaterLayoutDelegate> delegate;
@end
#import "ZHWaterLayout.h"

@interface ZHWaterLayout()
@property (nonatomic,strong) NSMutableArray *attriArray;
//用來(lái)存放所有列的高度
@property (nonatomic,strong) NSMutableArray *colsHeght;
//注意get方法要想提示寫(xiě)出,必須在這里先聲明!!!!
-(CGFloat)rowMargin;
-(CGFloat)columMargin;
-(NSInteger)columCount;
-(UIEdgeInsets)edgeInsets;

@end
//默認(rèn)值
static const CGFloat rowMargin = 10;//行距
static const CGFloat colMargin = 10;//列距
static const NSInteger col = 3;//默認(rèn)列數(shù)
static const UIEdgeInsets edgeInsets = {10,10,10,10};//內(nèi)邊距

@implementation ZHWaterLayout
//數(shù)據(jù)處理get方法
-(CGFloat)rowMargin{
    if ([self.delegate respondsToSelector:@selector(rowMarginWaterLayout:)]) {
        return [self.delegate rowMarginWaterLayout:self];
    }else{
        return rowMargin;
    }
}
-(CGFloat)columMargin{
    if ([self.delegate respondsToSelector:@selector(columMarginWaterLayout:)]) {
        return [self.delegate columMarginWaterLayout:self];
    }else{
        return colMargin;
    }
}
-(NSInteger)columCount{
    if ([self.delegate respondsToSelector:@selector(columCountWaterLayout:)]) {
        return [self.delegate columCountWaterLayout:self];
    }else{
        return col;
    }
}
-(UIEdgeInsets)edgeInsets{
    if ([self.delegate respondsToSelector:@selector(edgeInsetsWaterLayout:)]) {
        return [self.delegate edgeInsetsWaterLayout:self];
    }else{
       return edgeInsets;
    }
}
//記錄各列的高度
-(NSMutableArray *)colsHeght{
    if (_colsHeght == nil) {
        _colsHeght = [NSMutableArray array];
    }
    return _colsHeght ;
}
//存儲(chǔ)所有cell的UICollectionViewLayoutAttributes
-(NSMutableArray *)attriArray{
    if (_attriArray == nil) {
        _attriArray = [NSMutableArray array];
    }
    return _attriArray ;
}
//初始化操作
-(void)prepareLayout{
    [super prepareLayout];
    //1.每次刷新就回重新布局一次,重新清理一下數(shù)據(jù)
    //1.1清除高度數(shù)組并初始化
    [self.colsHeght removeAllObjects];
    //初始化數(shù)組
    for (int i= 0; i<self.columCount; i++) {
        [self.colsHeght addObject:@(self.edgeInsets.top)];
    }
    //1.2清除布局屬性數(shù)據(jù)
    [self.attriArray removeAllObjects];
    //2.計(jì)算出所有cell的UICollectionViewLayoutAttributes
    //共多少個(gè)item
    NSInteger rowcount = [self.collectionView numberOfItemsInSection:0];
    //遍歷計(jì)算出每一個(gè)
    for (int i = 0 ; i<rowcount; i++) {
        //創(chuàng)建UICollectionViewLayoutAttributes
        NSIndexPath *indexpath = [NSIndexPath indexPathForItem:i inSection:0];
        UICollectionViewLayoutAttributes *attri = [self layoutAttributesForItemAtIndexPath:indexpath];
        //添加UICollectionViewLayoutAttributes到數(shù)組中
        [self.attriArray addObject:attri];
    }
}
//返回rect內(nèi)的所有cell的UICollectionViewLayoutAttributes數(shù)組
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
    return self.attriArray;
}

//返回每一個(gè)cell的UICollectionViewLayoutAttributes
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
    //1.創(chuàng)建UICollectionViewLayoutAttributes對(duì)象
    UICollectionViewLayoutAttributes *attri = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    //2.設(shè)置UICollectionViewLayoutAttributes的frame屬性
    CGFloat collectW = self.collectionView.frame.size.width;
    //2.1計(jì)算出寬度
    CGFloat width = (collectW-self.edgeInsets.left-self.edgeInsets.right-(self.columCount-1)*self.columMargin)/self.columCount;
    //2.2根據(jù)外部模型數(shù)據(jù)傳進(jìn)來(lái)的高度計(jì)算出高度
    CGFloat height = [self.delegate waterLayout:self heightForItemAtIndex:indexPath.item andItemWidth:width];
    //2.3 計(jì)算出x
    //找出高度最短的那一列
//    __block NSUInteger desCol = 0;
//   __block CGFloat minColHeight = MAXFLOAT;
//    [self.colsHeght enumerateObjectsUsingBlock:^(NSNumber *  _Nonnull colHeight, NSUInteger idx, BOOL * _Nonnull stop) {
//        if (colHeight.doubleValue < minColHeight) {
//            minColHeight = colHeight.doubleValue;
//            desCol = idx;
//        }
//    }];
    //這樣遍歷可以少算一列
    NSInteger desCol = 0;
    CGFloat minColHeight = [self.colsHeght[0] doubleValue];
    for (NSInteger i = 1; i<self.columCount; i++) {
        //獲取第一列的高度
        CGFloat colH = [self.colsHeght[i] doubleValue];
        if (colH<minColHeight) {
            minColHeight = colH;
            desCol = i;
        }
    }
    CGFloat x = self.edgeInsets.left + desCol*(width + self.columMargin);
    //2.4計(jì)算出y值
    CGFloat y = minColHeight;//第一行時(shí)不加rowmargin
    if (y != self.edgeInsets.top) {
        y += self.rowMargin;
    }
    //3.賦值frame
    attri.frame = CGRectMake(x,y, width, height);
    //4.更新高度數(shù)組
    self.colsHeght[desCol] =@(CGRectGetMaxY(attri.frame)) ;
    return attri;
}

//返回collectionView的contentsize
-(CGSize)collectionViewContentSize{
    CGFloat maxColHeight = [self.colsHeght[0] doubleValue];
    for (NSInteger i = 1; i<self.columCount
         ; i++) {
        //獲取第一列的高度
        CGFloat colH = [self.colsHeght[i] doubleValue];
        if (colH>maxColHeight) {
            maxColHeight = colH;
        }
    }
    return CGSizeMake(0, maxColHeight+self.edgeInsets.bottom);
}

@end

demo的Github地址

效果圖如下:

2.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末陷嘴,一起剝皮案震驚了整個(gè)濱河市揍移,隨后出現(xiàn)的幾起案子拆讯,更是在濱河造成了極大的恐慌裁蚁,老刑警劉巖莫矗,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件视译,死亡現(xiàn)場(chǎng)離奇詭異浆竭,居然都是意外死亡鬼贱,警方通過(guò)查閱死者的電腦和手機(jī)私沮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)始赎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人仔燕,你說(shuō)我怎么就攤上這事造垛。” “怎么了涨享?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵筋搏,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我厕隧,道長(zhǎng)奔脐,這世上最難降的妖魔是什么俄周? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮髓迎,結(jié)果婚禮上峦朗,老公的妹妹穿的比我還像新娘。我一直安慰自己排龄,他們只是感情好波势,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著橄维,像睡著了一般尺铣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上争舞,一...
    開(kāi)封第一講書(shū)人閱讀 51,231評(píng)論 1 299
  • 那天凛忿,我揣著相機(jī)與錄音,去河邊找鬼竞川。 笑死店溢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的委乌。 我是一名探鬼主播床牧,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼遭贸!你這毒婦竟也來(lái)了戈咳?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤革砸,失蹤者是張志新(化名)和其女友劉穎除秀,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體算利,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年泳姐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了效拭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡胖秒,死狀恐怖缎患,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情阎肝,我是刑警寧澤挤渔,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站风题,受9級(jí)特大地震影響判导,放射性物質(zhì)發(fā)生泄漏嫉父。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一眼刃、第九天 我趴在偏房一處隱蔽的房頂上張望绕辖。 院中可真熱鬧,春花似錦擂红、人聲如沸仪际。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)树碱。三九已至,卻和暖如春变秦,著一層夾襖步出監(jiān)牢的瞬間成榜,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工伴栓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留伦连,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓钳垮,卻偏偏與公主長(zhǎng)得像惑淳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子饺窿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)歧焦、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,096評(píng)論 4 62
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,085評(píng)論 25 707
  • 1. 前幾天忽然看到自己年末時(shí)寫(xiě)的一篇文章舰涌,為了應(yīng)“過(guò)年回家被相親”的景,寫(xiě)了一篇《我不著急戀愛(ài)你稚,我想變得更好一點(diǎn)...
    離離離離離晨閱讀 532評(píng)論 9 16
  • 做微商不要總是想著別人可以帶給你什么瓷耙! 要多想想自己可以帶給別人什么! 做微商不要把利益放在第一位刁赖!要把人情放在第...
    筱雅的致雅閱讀 190評(píng)論 0 0
  • (≧?≦)/
    5d626066ce21閱讀 85評(píng)論 0 0