zoukankan      html  css  js  c++  java
  • UICollectionView自定义布局(石工布局)

    UICollectionView自定义布局(石工布局)


    效果:

    MKMasonryViewLayout调用顺序


    1. numberOfSectionsInCollectionView(dataSource)
      • (计算section个数)
    • numberOfItemsInSection(dataSource)
      • (计算section中item的个数)
    • prepareLayout (layout)
      • (初始化布局)(调用了heightForItemAtIndexPath)
    • heightForItemAtIndexPath(delegate)
      • (多次调用计算每个Cell的高度)
    • collectionViewContentSize(layout)
      • (计算集合视图的大小)
    • layoutAttributesForElementsInRect(layout)(计算给定区域中cell的位置 ) + collectionViewContentSize
      • (每次调用layoutAttributesForElementsInRect之后还会调用一次这个方法,所以可以计算一次然后保存这个值ContentSize)
    • cellForItemAtIndexPath (datasource)
      • (获取当前可视区域的cell)

    MKMasonryViewLayout.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
    

    MKMasonryViewLayout.m

    #import "MKMasonryViewLayout.h"
    
    @interface MKMasonryViewLayout (/*Private Methods*/)
    @property (nonatomic, strong) NSMutableDictionary *lastYValueForColumn;
    @property (strong, nonatomic) NSMutableDictionary *layoutInfo;
    @end
    
    @implementation MKMasonryViewLayout
    
    -(void) prepareLayout {
    
    
    NSLog(@" prepareLayout ");
    
    self.numberOfColumns = 3;//一行cell的数量
    self.interItemSpacing = 12.5;//每行之间cell的间距
    
    self.lastYValueForColumn = [NSMutableDictionary dictionary];
    CGFloat currentColumn = 0;
    
    
    CGFloat fullWidth = self.collectionView.frame.size.width;
    CGFloat availableSpaceExcludingPadding = fullWidth - (self.interItemSpacing * (self.numberOfColumns + 1));
    //计算cell宽度
    CGFloat itemWidth = availableSpaceExcludingPadding / self.numberOfColumns;
    
    //储存 UICollectionViewLayoutAttributes
    self.layoutInfo = [NSMutableDictionary dictionary];
    NSIndexPath *indexPath;
    NSInteger numSections = [self.collectionView numberOfSections];
    
    for(NSInteger section = 0; section < numSections; section++)  {
        
        NSInteger numItems = [self.collectionView numberOfItemsInSection:section];
        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;
            //存入layoutInfo
            self.layoutInfo[indexPath] = itemAttributes;
        }
    }
    }
    
    //计算给定区域中的物件 rect其实就是当前可视区域的rect
    - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
    
    NSLog(@" layoutAttributesForElementsInRect rect is %f %f %f %f",rect.origin.x,rect.origin.y,rect.size.width,rect.size.height);
    
    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;
    }
    
    //计算集合视图的大小 每次调用layoutAttributesForElementsInRect之后都会调用此方法,所以可以计算一次然后保存这个值ContentSize
    -(CGSize) collectionViewContentSize {
    NSLog(@" collectionViewContentSize " );
    NSUInteger currentColumn = 0;
    CGFloat maxHeight = 0;
    do {
        CGFloat height = [self.lastYValueForColumn[@(currentColumn)] doubleValue];
        if(height > maxHeight)
            maxHeight = height;
        currentColumn ++;
    } while (currentColumn < self.numberOfColumns);
    NSLog(@" collectionViewContentSize %f %f ",self.collectionView.frame.size.width,maxHeight);
    return CGSizeMake(self.collectionView.frame.size.width, maxHeight);
    }
    
    @end
  • 相关阅读:
    【IOS】ObjectC 中的Selector 概念
    iOS开发笔记 3、iOS基础
    iOS开发笔记 2、Cocoa简明
    iOS开发笔记 4、iOS中的Cocoa、设计模式等
    iOS开发笔记 5、开发工具Xcode,Inteface Builder
    iOS开发笔记 8、真机调试和发布软件
    移动App如何收费的模式和步骤分析
    带滚动条的二级黑色竖直菜单(CSS实现)
    很是动感的一款js伸缩、关闭菜单
    JS实现类似腾讯QQ折叠菜单
  • 原文地址:https://www.cnblogs.com/sunyanyan/p/5251271.html
Copyright © 2011-2022 走看看