瀑布流的简单自定义

#import <UIKit/UIKit.h>

@class UICollectionViewFlowWaterLayout;

@protocol UICollectionViewFlowWaterDelegate <UICollectionViewDelegate>

- (CGFloat)collectionView:(UICollectionView *)c layout:(UICollectionViewFlowWaterLayout *)collectionViewLayout heightForItemAtIndextPath:(NSIndexPath*)p;

//这里需要代理返回区头的高

-(CGFloat)collectionView:(UICollectionView *)c layoutWithHeader:(UICollectionViewFlowWaterLayout *)collectionViewLayout heightForHeaderAtIndextPath:(NSIndexPath*)indexPath;

@end

@interface UICollectionViewFlowWaterLayout : UICollectionViewLayout

@property (nonatomic,assign) NSInteger HeaderHeight;

//列数

@property (nonatomic,assign) NSInteger columnCount;

//每一个 item 的宽度

@property (nonatomic,assign) CGFloat itemWidth;

//每个 section 的偏移量

@property (nonatomic,assign) UIEdgeInsets sectionInset;

@property (nonatomic,assign) id<UICollectionViewFlowWaterDelegate> delegate;

@end

------------------------------------

#import "UICollectionViewFlowWaterLayout.h"

@interface UICollectionViewFlowWaterLayout ()

//记录当前的item 个数

@property (nonatomic,assign) NSInteger itemCount;

//记录间隙的宽度

@property (nonatomic,assign) CGFloat interitemSpacing;

//用来记录每一列的高度

@property (nonatomic,retain) NSMutableArray *columnHeights;

@property (nonatomic,retain) NSMutableArray *attributes;

@property (nonatomic,assign)NSInteger HeaderWithHeight;

@end

@implementation UICollectionViewFlowWaterLayout

- (void)dealloc {

self.columnHeights = nil;

self.attributes = nil;

[super dealloc];

}

- (id)init {

self = [super init];

if (self) {

[self initData];

}

return self;

}

- (void)initData {

_itemWidth      = 140.0f;

_columnCount    = 2;

_sectionInset   = UIEdgeInsetsZero;

}

- (void)setColumnCount:(NSInteger)columnCount {

if (_columnCount != columnCount) {

_columnCount = columnCount;

//调用 ‘invalidateLayout’ 不会使布局立即响应, collection View 会检查当前布局是否是最新布局,如果不是则更新。也就是说多次调用 ‘invalidateLayout’ 不会引起布局的重复更新;

[self invalidateLayout];

}

}

- (void)setItemWidth:(CGFloat)itemWidth {

if (_itemWidth != itemWidth) {

_itemWidth = itemWidth;

[self invalidateLayout];

}

}

- (void)setSectionInset:(UIEdgeInsets)sectionInset {

if (!UIEdgeInsetsEqualToEdgeInsets(_sectionInset, sectionInset)) {

_sectionInset = sectionInset;

[self invalidateLayout];

}

}

#pragma mark - Override

//预先计算需要提供 布局信息 告诉 collection View 每个 item 的绘画属性

//用layout 对象调用invalidateLayout 来开始布局过程,首先会调用prepareLayout

- (void)prepareLayout {

[super prepareLayout];

//首先要获取collection View 当前section上的item 的个数

_itemCount = [[self collectionView] numberOfItemsInSection:0];

//断言 不足一列 就报错

NSAssert(_columnCount > 1, @"当前瀑布流的列数必须大于1");

//开始布局设置每一个item 的位置坐标和属性绘画

//拿到当前绘制collection view 内容的宽度

//也即是在多宽的位置上绘制

CGFloat width = self.collectionView.frame.size.width - _sectionInset.left -_sectionInset.right;

//计算一个间隙的宽度

_interitemSpacing = floorf(width - _columnCount*_itemWidth)/(_columnCount - 1);

self.attributes = [NSMutableArray arrayWithCapacity:_itemCount];

self.columnHeights = [NSMutableArray arrayWithCapacity:_columnCount];

for (NSInteger idx = 0; idx < _columnCount; idx++) {

//        _columnHeights[idx] = @(_sectionInset.top);

[_columnHeights addObject:@(_sectionInset.top)];

}

NSLog(@"%@",_columnHeights);

//配置 每一个item 的绘制属性

//遍历下标

for (NSInteger idx = 0; idx < _itemCount; idx++) {

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

//拿到item 的高度

CGFloat itemHeight = [self.delegate collectionView:self.collectionView layout:self heightForItemAtIndextPath:indexPath];

//获取最低列的位置

NSInteger columnIdex = [self getMinHeightColumnIndex];

//设置没有个item 的xy

CGFloat xOffset = _sectionInset.left + (_itemWidth+_interitemSpacing)*columnIdex;

CGFloat yOffset = [(_columnHeights[columnIdex]) floatValue];

//设置每一个item 的绘画特性

//区头的高,非常重要,添加到attributesItem上面

_HeaderWithHeight =[self.delegate collectionView:self.collectionView layoutWithHeader:self heightForHeaderAtIndextPath:indexPath];

UICollectionViewLayoutAttributes *attributesItem = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

attributesItem.frame = CGRectMake(xOffset, yOffset+_HeaderWithHeight, _itemWidth, itemHeight);

[_attributes addObject:attributesItem];

_columnHeights[columnIdex] = @(yOffset + itemHeight + _interitemSpacing);

}

}

- (CGSize)collectionViewContentSize {

if (0 == self.itemCount) {

return CGSizeZero;

}

//这里需要返回一下区头的高度不然拉表的时候会有问题

CGSize contentSize = self.collectionView.frame.size;

NSInteger columnMaxIndex = [self getMaxHeightColumnIndex];

contentSize.height = [self.columnHeights[columnMaxIndex] floatValue] + self.sectionInset.bottom - self.interitemSpacing + _HeaderWithHeight;

return contentSize;

}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {

return (self.attributes)[indexPath.item];

}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {

return [self.attributes filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {

return CGRectIntersectsRect(rect,((UICollectionViewLayoutAttributes *)evaluatedObject).frame);

}]];

}

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{

return NO;

}

//find out min column index

- (NSInteger)getMinHeightColumnIndex {

__block NSInteger index = 0;

__block CGFloat tempIndex = MAXFLOAT;

[self.columnHeights enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

CGFloat temp = [obj floatValue];

if (temp < tempIndex) {

tempIndex = temp;

index = idx;

}

}];

return index;

}

//find out max column index

- (NSInteger)getMaxHeightColumnIndex {

__block NSInteger index = 0;

__block CGFloat tempIndex = 0;

NSLog(@"%@",self.columnHeights);

[self.columnHeights enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

CGFloat temp = [obj floatValue];

if (temp > tempIndex) {

tempIndex = temp;

index = idx;

}

}];

return index;

}

@end

--------具体的实现-----上面是自定义的cell

#import "ViewController.h"

#import "UICollectionViewFlowWaterLayout.h"

@interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewFlowWaterDelegate>{

}

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

UICollectionViewFlowWaterLayout *layout = [[UICollectionViewFlowWaterLayout alloc]init];

layout.columnCount = 2;

layout.itemWidth   = 150.0f;

layout.delegate    = self;

UICollectionView *collection = [[UICollectionView alloc]initWithFrame:self.view.bounds collectionViewLayout:layout];

[collection registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"kCellID"];

collection.backgroundColor = [UIColor redColor];

collection.dataSource = self;

collection.delegate   = self;

[self.view addSubview:collection];

}

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

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

return 10;

}

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

UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"kCellID" forIndexPath:indexPath];

cell.backgroundColor = [UIColor yellowColor];

return cell;

}

#pragma  mark --------------代理-----------------

//这里自定义区头的高度,同理可以自定义区尾这里非常重要

-(CGFloat)collectionView:(UICollectionView *)c layoutWithHeader:(UICollectionViewFlowWaterLayout *)collectionViewLayout heightForHeaderAtIndextPath:(NSIndexPath*)indexPath

{

CGFloat height = arc4random()%200 + 100.0f;

return height;

}

- (CGFloat)collectionView:(UICollectionView *)c layout:(UICollectionViewFlowWaterLayout *)collectionViewLayout heightForItemAtIndextPath:(NSIndexPath *)p {

CGFloat height = arc4random()%200 + 50.0f;

return height;

}

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath

{

NSLog(@"%ld",(long)indexPath.row);

}

@end

时间: 2024-10-10 12:33:56

瀑布流的简单自定义的相关文章

jQuery实现瀑布流的简单方法

HTML代码 <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>waterFall</title> <link rel="stylesheet" href="wf.css"> <script src="jquery.js">

瀑布流的简单实现

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #08fa95 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #4bd156 } p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #ffffff } p.p4 { margin: 0.0p

iOS开发之窥探UICollectionViewController(四) --一款功能强大的自定义瀑布流

在上一篇博客中<iOS开发之窥探UICollectionViewController(三) --使用UICollectionView自定义瀑布流>,自定义瀑布流的列数,Cell的外边距,Cell的最大以及最小高度是在我们的布局文件中是写死的,换句话说也就是不可配置的.为了循序渐进,由浅入深呢,上篇博客暂且那么写.不过那样写太过死板,本来使用起来比较灵活的自定义布局,如果把其配置参数给写死了,就相当于在笼中的猛兽,再厉害不也白扯蛮. 在今天这篇博客中我们要接着上篇博客中的Demo,使其自定义布局

ios图片瀑布流代码

ios瀑布流,实现简单的瀑布流视图布局,可以显示网络图片,下拉刷新,上拉加载更多. 下载:http://www.huiyi8.com/sc/9087.html ios图片瀑布流代码,布布扣,bubuko.com

iOS开发UI篇—自定义瀑布流控件(蘑菇街数据刷新操作)

iOS开发UI篇—自定义瀑布流控件(蘑菇街数据刷新操作) 一.简单说明 使用数据刷新框架: 该框架提供了两种刷新的方法,一个是使用block回调(存在循环引用问题,_ _weak),一个是使用调用. 问题:在进行下拉刷新之前,应该要清空之前的所有数据(在刷新数据这个方法中). 移除正在显示的cell: (1)把字典中的所有的值,都从屏幕上移除 (2)清除字典中的所有元素 (3)清除cell的frame,每个位置的cell的frame都要重新计算 (4)清除可复用的缓存池. 该部分的代码如下: 1

iOS开发之窥探UICollectionViewController(三) --使用UICollectionView自定义瀑布流

上篇博客的实例是自带的UICollectionViewDelegateFlowLayout布局基础上来做的Demo, 详情请看<iOS开发之窥探UICollectionViewController(二) --详解CollectionView各种回调>.UICollectionView之所以强大,是因为其具有自定义功能,这一自定义就不得了啦,自由度非常大,定制的高,所以功能也是灰常强大的.本篇博客就不使用自带的流式布局了,我们要自定义一个瀑布流.自定义的瀑布流可以配置其参数: 每个Cell的边距

iOS开发UI篇—自定义瀑布流控件(基本实现)

iOS开发UI篇—自定义瀑布流控件(基本实现) 一.基本实现 说明:在View加载的时候,刷新数据. 1.实现代码 YYViewController.m文件 1 // 2 // YYViewController.m 3 // 06-瀑布流 4 // 5 // Created by apple on 14-7-28. 6 // Copyright (c) 2014年 wendingding. All rights reserved. 7 // 8 9 #import "YYViewControll

iOS之简单瀑布流的实现

iOS之简单瀑布流的实现 前言 超简单的瀑布流实现,这里说一下笔者的思路,详细代码在这里. 实现思路 collectionView能实现各中吊炸天的布局,其精髓就在于UICollectionViewLayout,因此我们要自定义一个layout来继承系统的UICollectionViewLayout,所有工作都在这个类中进行. 1.定义所需属性 瀑布流的思路就是,从上往下,那一列最短,就把下一个item放在哪一列,因此我们需要定义一个字典来记录每一列的最大y值 每一个item都有一个attrib

iOS开发UI篇—自定义瀑布流控件(蘑菇街实现)

iOS开发UI篇—自定义瀑布流控件(蘑菇街瀑布流) 一.简单说明 关于瀑布流 1.是使用UIScrollView实现的 2.刷新数据(reloadData)方法里面做哪些事情 3.layoutSubviews方法里面做哪些事情 4.模仿UItableView进行设计 完善: 瀑布流控件第一次显示到屏幕上的时候自动的向数据源索要数据,而不需要手动调用.这需要监听View的显示,View的显示有一个方法,叫做willMoveToSuperview:在该方法中直接刷新一次数据即可. 二.把自定义的瀑布