使用UICollectionView
使用UICollectionView的流程:
1. 設定一個UICollectionViewFlowLayout
2. 使用這個設定的UICollectionViewFlowLayout來初始化UICollectionView
3. 設置代理對象
4. 繼承UICollectionViewCell設定重用的cell
源碼:
LargeUICollectionViewFlowLayout.h + LargeUICollectionViewFlowLayout.m
#import <UIKit/UIKit.h> @interface LargeUICollectionViewFlowLayout : UICollectionViewFlowLayout @end
#import "LargeUICollectionViewFlowLayout.h" @implementation LargeUICollectionViewFlowLayout - (instancetype)init { self = [super init]; if (self) { self.itemSize = CGSizeMake(70, 70); self.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0); self.minimumInteritemSpacing = 40.0f; self.minimumLineSpacing = 5.0f; } return self; } @end
ShowCollectionViewCell.h + ShowCollectionViewCell.m
#import <UIKit/UIKit.h> @interface ShowCollectionViewCell : UICollectionViewCell @end
#import "ShowCollectionViewCell.h" @implementation ShowCollectionViewCell - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor redColor]; } return self; } @end
RootViewController.h + RootViewController.m
#import <UIKit/UIKit.h> @interface RootViewController : UIViewController @end
#import "RootViewController.h" #import "ShowCollectionViewCell.h" #import "LargeUICollectionViewFlowLayout.h" static NSString *identify = @"ItemIdentifier"; @interface RootViewController ()<UICollectionViewDelegate, UICollectionViewDataSource> @property (nonatomic, strong) UICollectionView *collectionView; @end @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; // 初始化UICollectionView並指定一個UICollectionViewFlowLayout self.collectionView = \ [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:[LargeUICollectionViewFlowLayout new]]; // 給UICollectionViewCell注冊重用標示(collectionView會自動給我們創建重用的cell對象) [self.collectionView registerClass:[ShowCollectionViewCell class] forCellWithReuseIdentifier:@"ItemIdentifier"]; // 設置代理對象 self.collectionView.delegate = self; self.collectionView.dataSource = self; // 將UICollectionView添加進父視圖 [self.view addSubview:_collectionView]; } -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return 100; } -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { ShowCollectionViewCell *cell = \ [collectionView dequeueReusableCellWithReuseIdentifier:@"ItemIdentifier" forIndexPath:indexPath]; return cell; } @end
運行后效果如下:
很重要的參數如下所示:
在ShowCollectionViewCell.m中執行打印操作:
打印信息如下:
2014-05-19 16:52:58.873 UICollectionView[3077:60b] {{0, 0}, {70, 70}} A
2014-05-19 16:52:58.875 UICollectionView[3077:60b] {{125, 0}, {70, 70}} B
2014-05-19 16:52:58.875 UICollectionView[3077:60b] {{250, 0}, {70, 70}} C
2014-05-19 16:52:58.875 UICollectionView[3077:60b] {{0, 75}, {70, 70}} D
2014-05-19 16:52:58.876 UICollectionView[3077:60b] {{125, 75}, {70, 70}}
2014-05-19 16:52:58.876 UICollectionView[3077:60b] {{250, 75}, {70, 70}}
2014-05-19 16:52:58.876 UICollectionView[3077:60b] {{0, 150}, {70, 70}}
2014-05-19 16:52:58.877 UICollectionView[3077:60b] {{125, 150}, {70, 70}}
2014-05-19 16:52:58.877 UICollectionView[3077:60b] {{250, 150}, {70, 70}}
2014-05-19 16:52:58.877 UICollectionView[3077:60b] {{0, 225}, {70, 70}}
2014-05-19 16:52:58.878 UICollectionView[3077:60b] {{125, 225}, {70, 70}}
2014-05-19 16:52:58.878 UICollectionView[3077:60b] {{250, 225}, {70, 70}}
2014-05-19 16:52:58.878 UICollectionView[3077:60b] {{0, 300}, {70, 70}}
2014-05-19 16:52:58.879 UICollectionView[3077:60b] {{125, 300}, {70, 70}}
2014-05-19 16:52:58.879 UICollectionView[3077:60b] {{250, 300}, {70, 70}}
2014-05-19 16:52:58.879 UICollectionView[3077:60b] {{0, 375}, {70, 70}}
2014-05-19 16:52:58.880 UICollectionView[3077:60b] {{125, 375}, {70, 70}}
2014-05-19 16:52:58.901 UICollectionView[3077:60b] {{250, 375}, {70, 70}}
2014-05-19 16:52:58.901 UICollectionView[3077:60b] {{0, 450}, {70, 70}}
2014-05-19 16:52:58.902 UICollectionView[3077:60b] {{125, 450}, {70, 70}}
2014-05-19 16:52:58.902 UICollectionView[3077:60b] {{250, 450}, {70, 70}}
2014-05-19 16:52:58.902 UICollectionView[3077:60b] {{0, 525}, {70, 70}}
2014-05-19 16:52:58.903 UICollectionView[3077:60b] {{125, 525}, {70, 70}}
2014-05-19 16:52:58.903 UICollectionView[3077:60b] {{250, 525}, {70, 70}}
2014-05-19 16:53:24.995 UICollectionView[3077:60b] {{0, 600}, {70, 70}}
2014-05-19 16:53:24.996 UICollectionView[3077:60b] {{125, 600}, {70, 70}}
2014-05-19 16:53:24.996 UICollectionView[3077:60b] {{250, 600}, {70, 70}}
分析上述打印信息A,B不難發現:125 - 70 = 55 > 40,所以,minimumInteritemSpacing只是單元格間的最小間距而已.
分析A,D發現,75 - 70 = 5,與minimumLineSpacing設定一致,因為我們是垂直滾動,所以縱向方向的間距是一致的.
知道這些,我們來實現網絡請求照片牆的效果.
修改LargeUICollectionViewFlowLayout中的代碼如下:
self.itemSize = CGSizeMake(100, 150); // 單元格尺寸
self.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0); // 單元格邊緣
self.minimumInteritemSpacing = 10.0f; // 橫排單元格最小間隔
self.minimumLineSpacing = 10.0f; // 單元格最小行間距
修改ShowCollectionViewCell.h + ShowCollectionViewCell.m
#import <UIKit/UIKit.h> @interface ShowCollectionViewCell : UICollectionViewCell @property (nonatomic, strong) UIImageView *showImageView; @end
#import "ShowCollectionViewCell.h" @implementation ShowCollectionViewCell - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor whiteColor]; CGRect rect = self.bounds; rect.origin.x += 3; rect.origin.y += 3; rect.size.height -= 6; rect.size.width -= 6; _showImageView = [[UIImageView alloc] initWithFrame:rect]; [self addSubview:_showImageView]; } return self; } @end
RootViewController.m
#import "RootViewController.h" #import "ShowCollectionViewCell.h" #import "LargeUICollectionViewFlowLayout.h" #import "YXGCD.h" #import "SDWebImage.h" // 重用標示 static NSString *identify = @"ItemIdentifier"; // 數據源 #define SOURCE_DATA @"http://www.duitang.com/album/1733789/masn/p/0/100/" @interface RootViewController ()<UICollectionViewDelegate, UICollectionViewDataSource> @property (nonatomic, strong) UICollectionView *collectionView; @property (nonatomic, strong) NSMutableArray *dataArray; // 數據源 @end @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; // 初始化數據源 _dataArray = [[NSMutableArray alloc] init]; // 初始化UICollectionView並指定一個UICollectionViewFlowLayout self.collectionView = \ [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:[LargeUICollectionViewFlowLayout new]]; // 給UICollectionViewCell注冊重用標示(collectionView會自動給我們創建重用的cell對象) [self.collectionView registerClass:[ShowCollectionViewCell class] forCellWithReuseIdentifier:@"ItemIdentifier"]; // 設置代理對象 self.collectionView.delegate = self; self.collectionView.dataSource = self; // 將UICollectionView添加進父視圖 [self.view addSubview:_collectionView]; [[GCDQueue globalQueue] execute:^{ // 獲取json數據 NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:SOURCE_DATA]]; // 轉換數據 NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves|| NSJSONReadingMutableContainers error:nil]; if (dataDictionary) { NSArray *dataArray = dataDictionary[@"data"][@"blogs"]; for (NSDictionary *dic in dataArray) { NSLog(@"%@", dic[@"isrc"]); // 存儲數據 [_dataArray addObject:dic[@"isrc"]]; } } // 主線程更新 [[GCDQueue mainQueue] execute:^{ [self.collectionView reloadData]; }]; }]; } -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return [_dataArray count]; } -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { ShowCollectionViewCell *cell = \ [collectionView dequeueReusableCellWithReuseIdentifier:@"ItemIdentifier" forIndexPath:indexPath]; [cell.showImageView setImageWithURL:[NSURL URLWithString:_dataArray[indexPath.row]]]; return cell; } @end
效果圖如下:
一款顯示壁紙的軟件就這么搞定雛形了......
我們來嘗試一下實時更換layout讓圖片自動布局,效果如下:
源碼:

#import "RootViewController.h" #import "ShowCollectionViewCell.h" #import "LargeUICollectionViewFlowLayout.h" #import "AnotherCollectionViewFlowLayout.h" #import "YXGCD.h" #import "SDWebImage.h" // 重用標示 static NSString *identify = @"ItemIdentifier"; // 數據源 #define SOURCE_DATA @"http://www.duitang.com/album/1733789/masn/p/0/100/" @interface RootViewController ()<UICollectionViewDelegate, UICollectionViewDataSource> @property (nonatomic, strong) UICollectionView *collectionView; @property (nonatomic, strong) LargeUICollectionViewFlowLayout *largeLayout; @property (nonatomic, strong) AnotherCollectionViewFlowLayout *anotherLayout; @property (nonatomic, strong) NSMutableArray *dataArray; // 數據源 @end @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; // 初始化數據源 _dataArray = [[NSMutableArray alloc] init]; // 初始化兩種布局 _largeLayout = [LargeUICollectionViewFlowLayout new]; _anotherLayout = [AnotherCollectionViewFlowLayout new]; // 初始化UICollectionView並指定一個UICollectionViewFlowLayout self.collectionView = \ [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:_largeLayout]; // 給UICollectionViewCell注冊重用標示(collectionView會自動給我們創建重用的cell對象) [self.collectionView registerClass:[ShowCollectionViewCell class] forCellWithReuseIdentifier:@"ItemIdentifier"]; // 設置代理對象 self.collectionView.delegate = self; self.collectionView.dataSource = self; // 將UICollectionView添加進父視圖 [self.view addSubview:_collectionView]; [[GCDQueue globalQueue] execute:^{ // 獲取json數據 NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:SOURCE_DATA]]; // 轉換數據 NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves|| NSJSONReadingMutableContainers error:nil]; if (dataDictionary) { NSArray *dataArray = dataDictionary[@"data"][@"blogs"]; for (NSDictionary *dic in dataArray) { NSLog(@"%@", dic[@"isrc"]); // 存儲數據 [_dataArray addObject:dic[@"isrc"]]; } } // 主線程更新 [[GCDQueue mainQueue] execute:^{ [self.collectionView reloadData]; // 3s后切換布局動畫 [[GCDQueue mainQueue] execute:^{ [_largeLayout invalidateLayout]; [_collectionView setCollectionViewLayout:_anotherLayout animated:YES]; } afterDelay:NSEC_PER_SEC * 3]; }]; }]; } -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return [_dataArray count]; } -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { ShowCollectionViewCell *cell = \ [collectionView dequeueReusableCellWithReuseIdentifier:@"ItemIdentifier" forIndexPath:indexPath]; [cell.showImageView setImageWithURL:[NSURL URLWithString:_dataArray[indexPath.row]]]; return cell; } @end
AnotherCollectionViewFlowLayout.h + AnotherCollectionViewFlowLayout.m
#import <UIKit/UIKit.h> @interface AnotherCollectionViewFlowLayout : UICollectionViewFlowLayout @end
#import "AnotherCollectionViewFlowLayout.h" @implementation AnotherCollectionViewFlowLayout - (instancetype)init { self = [super init]; if (self) { self.itemSize = CGSizeMake(150, 200); // 單元格尺寸 self.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0); // 單元格邊緣 self.minimumInteritemSpacing = 10.0f; // 橫排單元格最小間隔 self.minimumLineSpacing = 20.0f; // 單元格最小行間距 } return self; } @end
幾個核心的地方:(布局變化時自動匹配對於UICollectionView很重要哦)
so easy :)