类似于秒拍的自定义UICollection布局

我们很容易的可以获取到多个,一模一样的UICoectionCell,但是经常见到的一些视屏类应用的cell都是不一样大小的,面对这种情况,其实我们可以自定义UICollection的一个属性UICollectionViewFlowLayout,这本身就是一个UIColection的布局类
下面直接上代码:
1.自定义的 DG_CollectionFlowLayout
.h文件
#import 
@class DG_CollectionFlowLayout;
@protocol  DG_CollectionFlowLayoutDelegate
@required
**//计算高度**
- (CGFloat)CollectionFlowLayout:(DG_CollectionFlowLayout*)DG_CollectionFlowLayout heightForWidth:(CGFloat)width indexPath:(NSIndexPath *)indexpath;
@end
@interface DG_CollectionFlowLayout : UICollectionViewFlowLayout
**//每一行的间距 (row 行 column列 margin间距)**
@property (nonatomic, assign)CGFloat rowMargin;
//列间距
@property (nonatomic, assign)CGFloat columnMargin;
//允许的最大的列数
@property (nonatomic, assign)CGFloat columnCount;
//四边间距
@property (nonatomic, assign)UIEdgeInsets sectionInset;
//实现DG_CollectionFlowLayout协议
@property (nonatomic, assign)id delegate;

.m文件
#import "DG_CollectionFlowLayout.h"
@interface DG_CollectionFlowLayout ()
@property (nonatomic, strong)NSMutableDictionary *maxYDict;
//存放布局属性
@property (nonatomic ,strong)NSMutableArray *attrsArr;
@end
@implementation DG_CollectionFlowLayout
- (instancetype)init {  
if ([super init]) {       
  self.columnMargin = 10;     
  self.rowMargin = 10;    
  self.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);    
  self.columnCount = 2;  //最大列数
  }  
return self;
}
- (NSMutableDictionary *)maxYDict {  
  if (!_maxYDict) {      
       _maxYDict = [NSMutableDictionary dictionary];  
       for (int i = 0; i< self.columnCount; i++) {       
            NSString *column = [NSString stringWithFormat:@"%d",i];    
            self.maxYDict[column] = @"0";      
        } 
   } 
  return _maxYDict;
}
- (NSMutableArray *)attrsArr {   
     if (!_attrsArr) {       
         _attrsArr = [NSMutableArray array];
     }   
 return _attrsArr;
}
***#pragma mark 以下方法每次滑动都会调用***
- (void)prepareLayout {   
    for (int i = 0; i < self.columnCount; i++) {   
    NSString *column = [NSString stringWithFormat:@"%d",i];    
    self.maxYDict[column] = @(self.sectionInset.top);
   }   
   [self.attrsArr removeAllObjects];      
   //1.查看共有多少元素   
   NSInteger count = [self.collectionView numberOfItemsInSection:0];  
   //2.遍历每一个item属性  
for (int i = 0; i < count; i++) {     
    //取出布局属性       
      UICollectionViewLayoutAttributes *attr = [self layoutAttributesForItemAtIndexPath:   [NSIndexPath indexPathForItem:i inSection:0]];   
    //4.添加到数组中    
  [self.attrsArr addObject:attr]; 
  }}

**//设置允许每个collectionView的content的宽,高**
//这个方法会被调用两次 prepareLayout方法后调一次 layoutAttributesForElementsInRect:方法后会再调用一次
- (CGSize)collectionViewContentSize {   
__block NSString *maxColumn= @"0";   
[self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL * stop) {    
  if ([maxY floatValue] > [self.maxYDict[maxColumn] floatValue]) {  
        maxColumn = column;      
}    }];      
return CGSizeMake(0, [self.maxYDict[maxColumn] floatValue] + self.sectionInset.bottom);
}
***//允许查找集合视图的布局***
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{ 
  return YES;
}
**/** * **
**在这个方法里实现布局 * * **
**@param indexPath 指定的为位置 * * **
**@return  返回layout attributes 的实例**
** */**
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{       
__block NSString *miniColumn = @"0";  
[self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL * stop) {     
  if ([maxY floatValue] < [self.maxYDict[miniColumn] floatValue]) {  
        miniColumn = column;   
    }        
  }];       
    //计算frame 
  CGFloat width = (CGRectGetWidth(self.collectionView.frame) - self.sectionInset.left - self.sectionInset.right - self.columnMargin * (self.columnCount - 1))/self.columnCount;   
  CGFloat height = [self.delegate CollectionFlowLayout:self heightForWidth:width indexPath:indexPath];   
CGFloat x = self.sectionInset.left + (width + self.columnMargin)*[miniColumn intValue];   
CGFloat y = [self.maxYDict[miniColumn] floatValue] + self.rowMargin;   
self.maxYDict[miniColumn] = @(height + y);    
  UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 
  attr.frame = CGRectMake(x, y, width, height);        
  return attr;
}
**//设置每个 cell的大小及位置**
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect{
return self.attrsArr;
}
@end
2.上面两个文件,自定义的布局类DG_CollectionFlowLayout就搞定了,接下来我们自己定义CollectionCell
#import
@interface DGCollectionCell : UICollectionViewCell
@property (nonatomic, strong)UILabel *titleLabel;
@property (nonatomic, strong)UILabel *createTimeLabel;
@property (nonatomic, strong)UIImageView *themeImageView;
@end

#import "DGCollectionCell.h"
@implementation DGCollectionCell
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_titleLabel = [[UILabel alloc] init];
_titleLabel.backgroundColor = [UIColor blackColor];
_titleLabel.alpha = 0.4;
_titleLabel.text = @"美女";
_titleLabel.textColor = [UIColor whiteColor];

_createTimeLabel = [[UILabel alloc]init];
_createTimeLabel.backgroundColor = [UIColor blackColor];
_createTimeLabel.alpha = 0.4;
_createTimeLabel.text = @"2015-11-4 17:23";
_createTimeLabel.textColor = [UIColor greenColor];

_themeImageView = [[UIImageView alloc]init];
_themeImageView.image = [UIImage imageNamed:@"meinv.jpg"];

[self.contentView addSubview:_themeImageView];
[self.contentView addSubview:_titleLabel];
[self.contentView addSubview:_createTimeLabel];
}
return self;
}
/**
*  在这里可以布局contentView里面的控件
*
*  @param layoutAttributes 直接继承于NSObject 形式上类似于CALayer
*/
- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
       _themeImageView.frame = CGRectMake(0, 0, layoutAttributes.frame.size.width, layoutAttributes.frame.size.height);
_titleLabel.frame = CGRectMake(0, layoutAttributes.frame.size.height-42, layoutAttributes.frame.size.width, 21);
_createTimeLabel.frame = CGRectMake(0, CGRectGetMaxY(_titleLabel.frame), layoutAttributes.frame.size.width, 21);
}
@end
3.最重要的还是怎么用,应该不难,注释也很清楚
#import "ViewController.h"
#import "DGCollectionCell.h"#import "DG_CollectionFlowLayout.h"
@interface ViewController ()
@property (nonatomic, strong) UICollectionView *collectionView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initCollectionView];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)initCollectionView {
**DG_CollectionFlowLayout *flowLayout = [[DG_CollectionFlowLayout alloc] init];**
**flowLayout.delegate = self;**
self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:**flowLayout**];
self.collectionView.backgroundColor = [UIColor redColor];
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
[self.view addSubview:self.collectionView];
[self.collectionView registerClass:[DGCollectionCell class] forCellWithReuseIdentifier:@"cell"];
}
**//下面是我们自定义布局类的代理方法**
**- (CGFloat)CollectionFlowLayout:(DG_CollectionFlowLayout *)DG_CollectionFlowLayout heightForWidth:(CGFloat)width indexPath:(NSIndexPath *)indexpath {**
**if (indexpath.row%3==0) {**
**return 100;**
**} else if (indexpath.row%3 == 1) {**
**return 150;**
**} else {**
**return 200;**
**}**
**}**
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 25;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
DGCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor grayColor];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
NSLog(@"当前选中的item 是 %ld",(long)indexPath.row);
}

效果图如下:

类似于秒拍的自定义UICollection布局_第1张图片

[点我获取源码]https://pan.baidu.com/s/1pLCxlQb

你可能感兴趣的:(类似于秒拍的自定义UICollection布局)