UICollectionView

  1 #import "ViewController.h"
  2 #import "Model.h"
  3 #import "MyCollectionViewCell.h"
  4 #import "UIImageView+WebCache.h"
  5 #import "CustomLayout.h"
  6 @interface ViewController ()<UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout,CustomLayoutDelegate>
  7 
  8 ///声明一个数组用于存储model的数据类
  9 @property (nonatomic,strong)NSMutableArray *saveModelArray;
 10 
 11 @end
 12 
 13 @implementation ViewController
 14 
 15 - (void)viewDidLoad {
 16     [super viewDidLoad];
 17     // Do any additional setup after loading the view, typically from a nib.
 18     
 19     //首先知道要显示的数据是数组套字典的格式
 20     //创建Model类用于处理数据
 21     //解析数据
 22     [self analysizeData];
 23     
 24     //创建UICollectionView
 25     [self createCollectionView];
 26     
 27     //现在效果图片发虚,不是我们真正想要的一个效果,用户体验相当不好,所以说我们需要自定义flowLayout显示图片
 28     
 29     
 30     
 31     
 32     
 33     
 34 }
 35 
 36 #pragma mark - 创建UICollectionView(在创建此视图之前必须设置UICollectionViewFlowLayout进行布局)
 37 - (void)createCollectionView{
 38     /*
 39     //1.创建UICollectionViewFlowLayout
 40     UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
 41     //设置行间距
 42     layout.minimumLineSpacing = 10;
 43     //设置列间距的
 44     layout.minimumInteritemSpacing = 10;
 45     //设置item大小的
 46     layout.itemSize = CGSizeMake(100, 100);
 47     //设置视图距离上左下右的一个距离
 48     layout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
 49     
 50     //设置头部和尾部的高度
 51     layout.headerReferenceSize = CGSizeMake(10, 10);
 52     layout.footerReferenceSize = CGSizeMake(10, 10);
 53     //设置滚动方向
 54     layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
 55      */
 56     
 57     //使用自定义的layout进行布局
 58     CustomLayout *layout = [[CustomLayout alloc] init];
 59     layout.delegate = self;
 60     
 61     //设置布局的一个宽度
 62     CGFloat width = ([[UIScreen mainScreen] bounds].size.width - 40)/3;
 63     //设置item的一个大小
 64     layout.itemSize = CGSizeMake(width, width);
 65     //设置距离上下左右的间距
 66     layout.sectionInsets = UIEdgeInsetsMake(10, 10, 10, 10);
 67 
 68     layout.insertItemSpacing = 10;
 69     layout.numberOfColumns = 3;
 70     
 71     
 72     //创建UICollectionView
 73     UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:[[UIScreen mainScreen] bounds] collectionViewLayout:layout];
 74     collectionView.delegate = self;
 75     collectionView.dataSource = self;
 76     collectionView.backgroundColor = [UIColor whiteColor];
 77     [self.view addSubview:collectionView];
 78     
 79     
 80     //千万不要忘记注册cell
 81     [collectionView registerClass:[MyCollectionViewCell class] forCellWithReuseIdentifier:@"MyCollectionViewCell"];
 82     
 83     
 84     
 85 }
 86 
 87 //设置item的高度
 88 - (CGFloat)heightItemForIndexpath:(NSIndexPath *)indexPath{
 89     
 90     //获取model的对象
 91     Model *model = _saveModelArray[indexPath.row];
 92     
 93     CGFloat width = ([UIScreen mainScreen].bounds.size.width - 40)/3;
 94     
 95     CGFloat height = (model.height / model.width) * width;
 96     
 97     return height;
 98     
 99 }
100 
101 #pragma mark - 实现相关的代理方法
102 //设置item的数量
103 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
104     
105     return _saveModelArray.count;
106 }
107 //设置区的个数
108 - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
109     return 1;
110 }
111 //设置cell的一个样式
112 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
113     
114     //重用池里取出与之对应的cell
115     MyCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyCollectionViewCell" forIndexPath:indexPath];
116     cell.backgroundColor = [UIColor whiteColor];
117     
118     //设置cell上显示的内容
119     //首先取出model对象
120     Model *model = _saveModelArray[indexPath.row];
121     //然后将model对象中字符串类型的url转换成NSURL类型,以备使用
122     NSURL *url = [NSURL URLWithString:model.thumbURL];
123     
124     [cell.imageView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"placeHoderImage.png"]];
125     
126     
127     
128     
129     return cell;
130     
131 }
132 
133 #pragma mark - 解析数据
134 -  (void)analysizeData{
135     
136     //读取文件
137     NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"json"];
138     
139     //因为准备的数据是json数据,所以解析要遵循json数据的解析方式
140     NSData *data = [NSData dataWithContentsOfFile:filePath];
141     NSMutableArray *array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
142     //给数组初始化
143     self.saveModelArray = [NSMutableArray array];
144     //使用for..in遍历取出数组中的字典,然后赋值给model,存储起来
145     for (NSDictionary *dic in array) {
146         //使用kvc给model赋值
147         Model *model = [[Model alloc] init];
148         [model setValuesForKeysWithDictionary:dic];
149         [_saveModelArray addObject:model];
150     }
151     
152     NSLog(@"%@",_saveModelArray);   
153    
154     
155 }
156 
157 - (void)didReceiveMemoryWarning {
158     [super didReceiveMemoryWarning];
159     // Dispose of any resources that can be recreated.
160 }
161 
162 @end
 1 #import <UIKit/UIKit.h>
 2 
 3 //第一步:创建继承与UICollectionViewLayout的类,声明一个协议,只是先一个代理方法
 4 
 5 @protocol CustomLayoutDelegate <NSObject>
 6 
 7 //用于获取item的高度
 8 - (CGFloat)heightItemForIndexpath:(NSIndexPath *)indexPath;
 9 
10 @end
11 
12 
13 @interface CustomLayout : UICollectionViewLayout
14 
15 //第二步:设置相关的属性(设置外部可以访问到的)
16 ///item的大小
17 @property (nonatomic,assign)CGSize itemSize;
18 ///设置collectionView的内间距
19 @property (nonatomic,assign)UIEdgeInsets sectionInsets;
20 
21 ///item间距的设置
22 @property (nonatomic,assign)CGFloat insertItemSpacing;
23 ///列的数目
24 @property (nonatomic,assign)NSInteger numberOfColumns;
25 
26 ///代理
27 @property (nonatomic,weak)id <CustomLayoutDelegate>delegate;
28 
29 
30 
31 
32 @end
  1 #import "CustomLayout.h"
  2 
  3 //第三步:声明一些不暴露在外部使用的属性,只有当前文件可以使用的
  4 @interface CustomLayout ()
  5 
  6 ///获取item的总数量
  7 @property (nonatomic,assign)NSInteger numberOfItems;
  8 
  9 ///存储每一列高度的数组
 10 @property (nonatomic,strong)NSMutableArray *columnHeights;
 11 
 12 ///存储距离上下左右的数组(x,y,w,h)
 13 @property (nonatomic,strong)NSMutableArray *itemAtrributes;
 14 
 15 ///存储item的x值
 16 @property (nonatomic,assign)CGFloat detalX;
 17 
 18 ///存储item相对应的y值
 19 @property (nonatomic,assign)CGFloat detalY;
 20 
 21 ///记录最短的列
 22 @property (nonatomic,assign)NSInteger shortestIndex;
 23 
 24 ///获取最长列的索引值
 25 - (NSInteger)p_indexForLongestColumn;
 26 
 27 ///获取最短列的索引值
 28 - (NSInteger)p_indexForShortestColumn;
 29 
 30 
 31 
 32 @end
 33 
 34 @implementation CustomLayout
 35 
 36 //第四步:懒加载一些数据源
 37 - (NSMutableArray *)columnHeights{
 38     if (!_columnHeights) {
 39         self.columnHeights = [NSMutableArray array];
 40     }
 41     
 42     return _columnHeights;
 43 }
 44 
 45 - (NSMutableArray *)itemAtrributes{
 46     if (!_itemAtrributes) {
 47         self.itemAtrributes = [NSMutableArray array];
 48     }
 49     
 50     return _itemAtrributes;
 51 }
 52 
 53 //第五步:实现获取最长列的方法
 54 - (NSInteger)p_indexForLongestColumn{
 55     //定义一个变量用于记录哪一列是最长列
 56     NSInteger longestIndex = 0;
 57     //当前最长列的一个高度
 58     CGFloat longestHeight = 0;
 59 
 60     //遍历数组取出相关数据然后返回
 61     for (int i = 0; i < self.numberOfColumns; i++) {
 62         //获取相关的一个高度
 63         CGFloat currentHeight = [self.columnHeights[i] floatValue];
 64         
 65         //判断选出最高的一个高度
 66         if (currentHeight > longestHeight) {
 67             longestHeight = currentHeight;
 68             longestIndex = i;
 69         }
 70     }
 71     
 72     return longestIndex;
 73 
 74 }
 75 
 76 //第六步:实现获取最短列的一个方法
 77 - (NSInteger)p_indexForShortestColumn{
 78     
 79     //记录索引
 80     NSInteger shortestIndex = 0;
 81 
 82     //记录最小的一个高度
 83     CGFloat shortestHeight = MAXFLOAT;
 84     
 85     //遍历赋值取出最小的下标
 86     for (int i = 0; i < self.numberOfColumns; i++) {
 87         //获取一个当前高度
 88         CGFloat currentHeight = [self.columnHeights[i] floatValue];
 89         if (currentHeight < shortestHeight) {
 90             shortestHeight = currentHeight;
 91             shortestIndex = i;
 92         }
 93     }
 94     return shortestIndex;
 95     
 96 }
 97 
 98 //第七步:实现给每一列添加top高度
 99 - (void)addHeightWithColumns{
100     
101     //遍历取出相关的数值
102     for (int i = 0;i < self.numberOfColumns;i++){
103         self.columnHeights[i] = @(self.sectionInsets.top);
104     }
105 
106 }
107 
108 //第八步:查找最短的列,并设置相关属性
109 // 查找最短的列,并设置相关属性
110 - (void)searchShortColumns
111 {
112     _shortestIndex = [self p_indexForShortestColumn];
113     CGFloat shortestH = [self.columnHeights[_shortestIndex] floatValue];
114     // 计算x值:内边距left + (item宽 + item的间距)* 索引
115     self.detalX = self.sectionInsets.left + (self.itemSize.width +self.insertItemSpacing) * _shortestIndex;
116     // 计算y值
117     self.detalY = shortestH + self.insertItemSpacing;
118     
119 }
120 
121 //第九步:查找最短的列,并设置相关属性
122 // 设置属性和frame
123 - (void)setFrame:(NSIndexPath *)indexPath
124 {
125     // 设置属性
126     UICollectionViewLayoutAttributes *layoutArr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
127     // 保存item的高
128     CGFloat itemHeight = 0;
129     if (_delegate && [_delegate respondsToSelector:@selector(heightItemForIndexpath:)]) {
130         // 使用代理方法获取item的高
131         itemHeight = [_delegate heightItemForIndexpath:indexPath];
132     }
133     // 设置frame
134     layoutArr.frame = CGRectMake(_detalX, _detalY, self.itemSize.width, itemHeight);
135     // 放入数组
136     [self.itemAtrributes addObject:layoutArr];
137     // 更新高度
138     self.columnHeights[_shortestIndex] = @(_detalY +itemHeight);
139 }
140 
141 //步骤十:在实现文件中必须要的实现三个方法
142 /*
143  - (void)prepareLayout 准备布局方法,在每个UICollectionViewLayout将要被使用的时候调用这个方法
144  
145  - (CGSize)collectionViewContentSize  计算每个item的大小,会走很多次
146  
147  - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 返回所有的item的位置信息和大小
148  */
149 
150 //第十一步:实现准备布局的代理方法
151 // 准备布局
152 - (void)prepareLayout
153 {
154     // 调用父类布局
155     [super prepareLayout];
156     [self addHeightWithColumns];
157     // 获取item的数量
158     self.numberOfItems = [self.collectionView numberOfItemsInSection:0];
159     // 为每一个item设置frame和indexPath
160     for(int i = 0;i < self.numberOfItems;i++)
161     {
162         // 查找最短的列,并设置相关属性
163         [self searchShortColumns];
164         // 设置indexPath
165         NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
166         [self setFrame:indexPath];
167     }
168 }
169 
170 //第十二步:计算每个item的大小
171 // 计算每个item的大小
172 - (CGSize)collectionViewContentSize
173 {
174     // 获取最长高度索引
175     NSInteger longerstIndex = [self p_indexForLongestColumn];
176     // 通过索引获取高度
177     CGFloat longestH = [self.columnHeights[longerstIndex] floatValue];
178     // 获取collectionView的Size
179     CGSize contentSize = self.collectionView.frame.size;
180     // 最大高度+bottom
181     contentSize.height = longestH + self.sectionInsets.bottom;
182     return contentSize;
183 }
184 
185 //第十三步:将每个item的布局返回
186 // 返回每一个item的布局
187 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
188 {
189     // 返回每一个item的Attribute
190     return self.itemAtrributes;
191     
192 }
193 
194 
195 
196 @end
1 #import <UIKit/UIKit.h>
2 
3 @interface MyCollectionViewCell : UICollectionViewCell
4 ///用来展示图片的控件
5 @property (nonatomic,strong)UIImageView *imageView;
6 
7 @end
 1 #import "MyCollectionViewCell.h"
 2 
 3 @implementation MyCollectionViewCell
 4 
 5 //重写初始化方法
 6 - (instancetype)initWithFrame:(CGRect)frame{
 7     self = [super initWithFrame:frame];
 8     if (self) {
 9         self.imageView = [[UIImageView alloc] init];
10         [self.contentView addSubview:self.imageView];
11     }
12     return self;
13 }
14 //设置控件的frame
15 - (void)layoutSubviews{
16     [super layoutSubviews];
17     self.imageView.frame = self.bounds;
18 }
19 
20 @end
 1 #import <Foundation/Foundation.h>
 2 
 3 @interface Model : NSObject
 4 
 5 ///图片的网址
 6 @property (nonatomic,strong)NSString *thumbURL;
 7 
 8 ///图片的宽
 9 @property (nonatomic,assign)NSInteger width;
10 
11 ///图片的高度
12 @property (nonatomic,assign)NSInteger height;
13 
14 @end
1 #import "Model.h"
2 
3 @implementation Model
4 
5 - (void)setValue:(id)value forUndefinedKey:(NSString *)key{
6     
7 }
8 
9 @end

 

posted @ 2016-03-09 19:20  恒远也  阅读(243)  评论(0编辑  收藏  举报