集合试图(UICollectionview)的灵活使用

1.相信大家都会很熟练使用UITableView了,但是今天给大家 介绍一个iOS6就已经引入的UICollectionView ,功能更加强大,更加灵活,学会使用它,会 帮你解决很多的问题的!它跟UITableView很相似,所以 熟练使用UICollectionView很简单!

2 。先列举一个简单的例子


集合试图(UICollectionview)的灵活使用_第1张图片
效果图1.png

我们可以看到这个流式布局,我们可以自定义 布局,继承与UICollectionViewFlowLayout

我现在将 主要代码 贴出来 ,希望对正在使用UICollectionView的同学有所帮助

自定义 布局,继承与 UICollectionViewFlowLayout
CoustomFlowLayOut.m

  • (instancetype)init
    {
    if (self = [super init]) {
    }
    return self;
    }

/**

  • 当collectionView的显示范围发生改变的时候,是否需要重新刷新布局
  • 一旦重新刷新布局,就会重新调用下面的方法:
    1.prepareLayout
    2.layoutAttributesForElementsInRect:方法
    */
  • (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
    {
    return YES;
    }

/**

  • 用来做布局的初始化操作(不建议在init方法中进行布局的初始化操作)
    */
  • (void)prepareLayout
    {
    [super prepareLayout];

    // 水平滚动
    self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    // 设置内边距
    CGFloat inset = (self.collectionView.frame.size.width - self.itemSize.width) * 0.5;
    self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);
    }

/**
UICollectionViewLayoutAttributes attrs;
1.一个cell对应一个UICollectionViewLayoutAttributes对象
2.UICollectionViewLayoutAttributes对象决定了cell的frame
/
/

  • 这个方法的返回值是一个数组(数组里面存放着rect范围内所有元素的布局属性)
  • 这个方法的返回值决定了rect范围内所有元素的排布(frame)
    */
  • (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
    {
    // 获得super已经计算好的布局属性
    NSArray *array = [super layoutAttributesForElementsInRect:rect] ;

    // 计算collectionView最中心点的x值
    CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5;

    // 在原有布局属性的基础上,进行微调
    for (UICollectionViewLayoutAttributes *attrs in array) {
    // cell的中心点x 和 collectionView最中心点的x值 的间距
    CGFloat delta = ABS(attrs.center.x - centerX);

      // 根据间距值 计算 cell的缩放比例
      CGFloat scale = 1 - delta / self.collectionView.frame.size.width;
      
      // 设置缩放比例
      attrs.transform = CGAffineTransformMakeScale(scale, scale);
    

    }
    return array;
    }

/**

  • 这个方法的返回值,就决定了collectionView停止滚动时的偏移量

*/

  • (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
    {
    // 计算出最终显示的矩形框
    CGRect rect;
    rect.origin.y = 0;
    rect.origin.x = proposedContentOffset.x;
    rect.size = self.collectionView.frame.size;

    // 获得super已经计算好的布局属性
    NSArray *array = [super layoutAttributesForElementsInRect:rect];

    // 计算collectionView最中心点的x值
    CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5;

    // 存放最小的间距值
    CGFloat minDelta = MAXFLOAT;
    for (UICollectionViewLayoutAttributes *attrs in array) {
    if (ABS(minDelta) > ABS(attrs.center.x - centerX)) {
    minDelta = attrs.center.x - centerX;
    }
    }

    // 修改原有的偏移量
    proposedContentOffset.x += minDelta;
    return proposedContentOffset;
    }

自定义cell的话,就是只有一张图片,这里不再赘述,控制器里
mainViewController.m

  • (void)viewDidLoad {
    [super viewDidLoad];

    // 创建布局
    CoustomFlowLayOut *layout = [[CoustomFlowLayOut alloc] init];
    layout.itemSize = CGSizeMake(100, 100);

    // 创建CollectionView
    CGFloat collectionW = self.view.frame.size.width;
    CGFloat collectionH = 200;
    CGRect frame = CGRectMake(0, 150, collectionW, collectionH);
    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:layout];
    collectionView.dataSource = self;
    collectionView.delegate = self;
    [self.view addSubview:collectionView];

    // 注册
    [collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([CYPhotoCell class]) bundle:nil] forCellWithReuseIdentifier:CYPhotoId];
    }

pragma mark -

  • (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
    {
    return 20;
    }

  • (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
    CYPhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CYPhotoId forIndexPath:indexPath];

    cell.imageName = [NSString stringWithFormat:@"%zd", indexPath.item + 1];

    return cell;
    }

pragma mark -

  • (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
    {
    NSLog(@"------%zd", indexPath.item);
    }
    @end

上边就是 主要的代码,就可以很简单的实现 上边图片的功能

大家还可能 见过商城中的 商品中的布局 ,类似是这样的,


集合试图(UICollectionview)的灵活使用_第2张图片
效果图.png

其实上边的这种效果也很容易实现,只要自己 自定义布局就行了,只是这个布局比 上边那种布局更复杂一点,但是整体的思路还是相同的,就是 自定义 布局,自定义cell,然后控制器 来利用使用它们,在这里 我将主要的代码贴出来,让大家参考,希望对大家 深入了解认识UICollectionView有好的帮助
同样的我先贴出 自定义layOut的 代码
.h中

import

@class MKMasonryViewLayout;

@protocol MKMasonryViewLayoutDelegate
@required

  • (CGFloat) collectionView:(UICollectionView) collectionView
    layout:(MKMasonryViewLayout
    ) layout
    heightForItemAtIndexPath:(NSIndexPath*) indexPath;
    @end

@interface MKMasonryViewLayout : UICollectionViewLayout
@property (nonatomic, assign) NSUInteger numberOfColumns;
@property (nonatomic, assign) CGFloat interItemSpacing;
@property (weak, nonatomic) IBOutlet id delegate;
@end

.m中

import "MKMasonryViewLayout.h"

@interface MKMasonryViewLayout (/Private Methods/)
@property (nonatomic, strong) NSMutableDictionary *lastYValueForColumn;
@property (strong, nonatomic) NSMutableDictionary *layoutInfo;
@end

@implementation MKMasonryViewLayout

-(void) prepareLayout {

//集合试图 布局 前 会调用这个方法,在这里将 布局物件的边框都计算好 缓存到某个地方

self.numberOfColumns = 3;
self.interItemSpacing = 12.5;

CGFloat currentColumn = 0;
CGFloat fullWidth = self.collectionView.frame.size.width;
CGFloat availableSpaceExcludingPadding = fullWidth - (self.interItemSpacing * (self.numberOfColumns + 1));
CGFloat itemWidth = availableSpaceExcludingPadding / self.numberOfColumns;//每个物件的宽度

self.lastYValueForColumn = [NSMutableDictionary dictionary];

self.layoutInfo = [NSMutableDictionary dictionary];
NSIndexPath *indexPath;
NSInteger numSections = [self.collectionView numberOfSections];

for(NSInteger section = 0; section < numSections; section++) {
//collectionView 是 横着 排列的,而不是 竖着排列的
NSInteger numItems = [self.collectionView numberOfItemsInSection:section];
//每个 section 上含有几个 nuMItems
for(NSInteger item = 0; item < numItems; item++){
indexPath = [NSIndexPath indexPathForItem:item inSection:section];

  UICollectionViewLayoutAttributes *itemAttributes =
  [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
  
  CGFloat x = self.interItemSpacing + (self.interItemSpacing + itemWidth) * currentColumn;
  CGFloat y = [self.lastYValueForColumn[@(currentColumn)] doubleValue];
  
  CGFloat height = [((id)self.collectionView.delegate)
                    collectionView:self.collectionView
                    layout:self
                    heightForItemAtIndexPath:indexPath];
  
  itemAttributes.frame = CGRectMake(x, y, itemWidth, height);
  y+= height;
  y += self.interItemSpacing;
  
  self.lastYValueForColumn[@(currentColumn)] = @(y);
  
  currentColumn ++;
  if(currentColumn == self.numberOfColumns) currentColumn = 0;
  self.layoutInfo[indexPath] = itemAttributes;
}

}
}

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

    NSMutableArray *allAttributes = [NSMutableArray arrayWithCapacity:self.layoutInfo.count];

    [self.layoutInfo enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath,
    UICollectionViewLayoutAttributes *attributes,
    BOOL *stop) {

    if (CGRectIntersectsRect(rect, attributes.frame)) {
    [allAttributes addObject:attributes];
    }
    }];
    return allAttributes;
    }

-(CGSize) collectionViewContentSize {

NSUInteger currentColumn = 0;
CGFloat maxHeight = 0;
do {
CGFloat height = [self.lastYValueForColumn[@(currentColumn)] doubleValue];
if(height > maxHeight)
maxHeight = height;
currentColumn ++;
} while (currentColumn < self.numberOfColumns);

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

@end

上边就是 完整的把想要的布局 给 布置好了,同样自定义cell这里也不 多谢,现在把 控制器的代码贴出来!

import "SCTViewController.h"

@interface SCTViewController ()

@end

@implementation SCTViewController

  • (void)viewDidLoad
    {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    }

  • (void)didReceiveMemoryWarning
    {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

  • (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {

    return 1;
    }

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

    return 40;
    }

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

    static NSString *CellIdentifier = @"Cell";
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier
    forIndexPath:indexPath];
    cell.backgroundColor = [UIColor redColor];
    return cell;
    }

// this will be called if our layout is UICollectionViewFlowLayout

  • (CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {

    CGFloat randomHeight = 100 + (arc4random() % 140);
    return CGSizeMake(100, randomHeight); // 100 to 240 pixels tall
    }

// this will be called if our layout is MKMasonryViewLayout

  • (CGFloat) collectionView:(UICollectionView) collectionView
    layout:(MKMasonryViewLayout
    ) layout
    heightForItemAtIndexPath:(NSIndexPath*) indexPath {

    // we will use a random height from 100 - 400

    CGFloat randomHeight = 100 + (arc4random() % 140);
    return randomHeight;
    }

@end

上边的代码就可以实现上图中所要实现的功能,希望可以帮到个位!希望个位提出宝贵意见!

你可能感兴趣的:(集合试图(UICollectionview)的灵活使用)