美文网首页
集合试图(UICollectionview)的灵活使用

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

作者: a457e74fe3a4 | 来源:发表于2017-12-12 20:49 被阅读0次

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

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


    效果图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 - <UICollectionViewDataSource>

    • (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 - <UICollectionViewDelegate>

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

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

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


    效果图.png

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

    import <UIKit/UIKit.h>

    @class MKMasonryViewLayout;

    @protocol MKMasonryViewLayoutDelegate <NSObject>
    @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<MKMasonryViewLayoutDelegate> 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<MKMasonryViewLayoutDelegate>)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 ()<UICollectionViewDataSource, UICollectionViewDelegate, MKMasonryViewLayoutDelegate, UICollectionViewDelegateFlowLayout>

    @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)的灵活使用

          本文链接:https://www.haomeiwen.com/subject/zmalixtx.html