瀑布流的實現全過程

1.建立繼承自UICollectionViewCell的l類ImageCell,將imageView和label聲明成屬性,而後重寫- initWithFrame:方法,初始化內部控件git

- (id)initWithFrame:(CGRect)framegithub

{json

    self = [super initWithFrame:frame];數組

    if (self) {佈局

        [self setupSubviews];atom

    }url

    return self;spa

}代理

 

- (void)setupSubviewsorm

{

    _imageView = [[UIImageView allocinitWithFrame:self.bounds];

    [self.contentView addSubview:_imageView];

    _numberLabel = [[UILabel allocinitWithFrame:CGRectMake(005020)];

    [_imageView addSubview:_numberLabel];

    

}

- (void)layoutSubviews

{

    [super layoutSubviews];

    

    _imageView.frame = self.bounds;

}

2:建立模型Model類,聲明好屬性

- (void)setValue:(id)value forUndefinedKey:(NSString *)key

{

//    if ([key isEqualToString:@"id"]) {

//        self.ID = value;

}

 

- (void)setValue:(id)value forKey:(NSString *)key

{

    [super setValue:value forKey:key];

    

    if ([key isEqualToString:@"width"]) {

        

        self.width = [value floatValue];

    }

    

    if ([key isEqualToString:@"height"]) {

        

        self.height = [value floatValue];

    }

    

}

 

3:建立一個瀑布流的佈局類繼承自NSObject,而後設置代理協議,並聲明屬性  

 

4:在這個自定義的WaterFlowLayout中實現各類佈局方法

//存放每一列的高度

@property (nonatomic, retain) NSMutableArray *columnHeightsArray;

 

//存放 每個item 屬性 包含 frame以及下標

@property (nonatomic, retain) NSMutableArray *attributesArray;

 @end

 

//獲取最小高度的方法

- (CGFloat)minHeight

{

    CGFloat min = 100000;

    for (NSNumber *height in _columnHeightsArray) {

        CGFloat h = [height floatValue];

        if (min > h) {

            min = h;

        }

    }

    return min;

}

 

//獲取最大值

- (CGFloat)maxHeight

{

    CGFloat max = 0;

    for (NSNumber *height in _columnHeightsArray) {

        CGFloat h = [height floatValue];

        if (max < h) {

            max = h;

        }

    }

    return max;

}

//最小高度的下標

- (NSUInteger)indexOfMinHeight

{

    NSUInteger index = 0;

    for (int i = 0; i < [_columnHeightsArray count]; i ++) {

        CGFloat height = [_columnHeightsArray[i] floatValue];

        if (height == [self minHeight]) {

            index = i;

            return index;

        }

    }

    return index;

}

 

//重寫父類的佈局方法

- (void)prepareLayout

{

    [super prepareLayout];

    

    _attributesArray = [[NSMutableArray alloc] init];

    

    _columnHeightsArray = [[NSMutableArray alloc] initWithCapacity:self.numberOfColumn];

    

    //給列高數組裏面的對象賦初值

    for (int i = 0; i < self.numberOfColumn; i ++) {

        [_columnHeightsArray addObject:@0.0];

    }

    

    CGFloat totalWidth = self.collectionView.frame.size.width;

    

    //建立 每一個item frame中的xy

    CGFloat x = 0;

    CGFloat y = 0;

    

    NSUInteger itemCount = [self.collectionView numberOfItemsInSection:0];

    

    for (int i = 0; i < itemCount; i ++) {

        //獲得集合視圖中 列間隙的個數

        NSUInteger numberOfSpace = self.numberOfColumn - 1;

        

        //代理對象執行代理方法,獲得 item之間的間隙大小

        CGFloat spaceWidth = [_delegate collectionView:self.collectionView layout:self minimumInteritemSpacingForSectionAtIndex:0];

        

        //求每列的寬度,也就是每一個itemwidth

        CGFloat width = (totalWidth - spaceWidth * numberOfSpace) / self.numberOfColumn;

        

        

        //獲取每個itemSize的大小

        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];

        

        //數據中原始圖片大小

        CGSize imageSize = [_delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath];

    

        //經過 約分公式獲得固定寬以後的高度是多少

        CGFloat height = width * imageSize.height / imageSize.width;

        

        

        UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

        

        //記錄每個item的大小和位置

        attribute.frame = CGRectMake(x, y, width, height);

        

        //數組保存每一個item的位置信息

        [_attributesArray addObject:attribute];

        

        NSLog(@"item = %d",i);

        NSLog(@"x = %.2f y = %.2f width = %.2f height = %.2f",x,y,width,height);

        

        //求列高最小的那一列的下標

        NSUInteger minHeightIndex = [self indexOfMinHeight];

        

        //求出最小列的高度

        CGFloat minHeight = [_columnHeightsArray[minHeightIndex] floatValue];

        

        //求出行高

        CGFloat lineHeight = [_delegate collectionView:self.collectionView layout:self minimumLineSpacingForSectionAtIndex:0];

        

        //上一次總的列高 加上 行高 加上新加上的itemheight,纔是如今這一列的總高度

        //minHeight爲最小列如今的高度

        //lineHeight爲行間距

        //height爲新加的item的高

        _columnHeightsArray[minHeightIndex] = [NSNumber numberWithFloat:minHeight + lineHeight + height];

        

        //從新算最小列高的下標

        minHeightIndex = [self indexOfMinHeight];

        

        //算下一次新加的itemxy

        x = (spaceWidth + width) * minHeightIndex;

        

        y = [self minHeight];

    }

}

 

//重寫這個方法,能夠返回集合視圖的總高度

- (CGSize)collectionViewContentSize

{

    return CGSizeMake(self.collectionView.frame.size.width, [self maxHeight]);

}

 

//這個方法不寫 集合視圖顯示不出來,這個方法是將保存的每一個item的信息告訴集合視圖,進行顯示。

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect

{

    return _attributesArray;

}

 //這是重寫的一個佈局方法,和系統的佈局方法就不同了,而後就能夠將這個類當成系統的UICollectionFlowLayout相同的方法使用了

 

#pragma mark -----WaterFlowDelegate-----

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath

{

    Model *model = _dataArray[indexPath.row];

    return CGSizeMake(model.width, model.height);

}

 

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section

{

    return UIEdgeInsetsMake(0, 0, 0, 0);

}

 

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section

{

    return 10;

}

 

 

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section

{

    return 5;

}

 

- (void)viewDidLoad {

    [super viewDidLoad];

//bundle文件中讀取原始數據  json格式

    NSString * filePath = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"json"];

    NSData * sourceData = [NSData dataWithContentsOfFile:filePath];

    

    //解析

    NSArray * sourceArray = [NSJSONSerialization JSONObjectWithData:sourceData options:NSJSONReadingMutableContainers error:nil];

    

    self.dataArray = [NSMutableArray arrayWithCapacity:40];

    

    //處理數據

    for (NSDictionary * dic in sourceArray) {

        

        Model * m = [[Model alloc] init];

        [m setValuesForKeysWithDictionary:dic];

        [_dataArray addObject:m];

        [m release];

    }

    

    //建立佈局對象

    WaterFlowLayout *flowLayout = [[WaterFlowLayout alloc] init];

    

    flowLayout.delegate = self;

    flowLayout.numberOfColumn = 3;

    

    //建立集合視圖

    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:[UIScreen mainScreen].bounds collectionViewLayout:flowLayout];

    collectionView.backgroundColor = [UIColor whiteColor];

    

    collectionView.delegate = self;

    collectionView.dataSource = self;

    

    //collectionView註冊一個cell

    [collectionView registerClass:[ImageCell class] forCellWithReuseIdentifier:@"aaa"];

    

    [self.view addSubview:collectionView];

    

    [collectionView release];

    [flowLayout release];

    

    // Do any additional setup after loading the view, typically from a nib.

}

 

#pragma mark -----DataSource-----

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section

{

    return [_dataArray count];

}

 

// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

{

    ImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"aaa" forIndexPath:indexPath];

    

    

    //獲取模型

    Model *model = self.dataArray[indexPath.row];

    

    NSURL *url = [NSURL URLWithString:model.thumbURL];

    

    [cell.imageView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"屏幕快照 2016-02-25 下午4.17.55.png"]];

    

//    cell.imageView.image = [UIImage imageNamed:@"8.png"];

    

//    cell.numberLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row];

    

    return cell;

}

這裏須要用到一個類SDWebImage的文件,將它上傳到了個人github上。

相關文章
相關標籤/搜索