[iOS]自定义UICollectionView 2-1--CollectionView的实现(定义与初始化)

我厂广招各路大神加入:job.koudaitong.com
可以发简历到 tianchi@qima-inc.com O(∩_∩)O~

接下来就是主要的CollectionView的实现。首先是头文件的实现,先定义一个用来区分Collection状态的枚举:

#import <UIKit/UIKit.h>

typedef enum {
    CS_Init,
    CS_More,
    CS_Refresh
}CollectionState;

然后定义delegate与DataSource:

@class iCollectionItem;
@protocol iCollectionDataSource;
@protocol iCollectionDelegate;

定义CollectionView:

@interface iCollectionView : UIScrollView<UIScrollViewDelegate>

@property (weak, nonatomic) id<iCollectionDataSource> dataSource;
@property (weak, nonatomic) id<iCollectionDelegate> customDelegate;

-(iCollectionItem *)dequeueReusableItemWithIdentifier:(NSString *)identifier;
-(void)addItemsIntoDic;//废弃不用
-(void)itemClickedAtPoint:(CGPoint)point;
-(void)reloadData;
-(iCollectionItem *)getItemAtPoint:(CGPoint)point;

@property (strong,nonatomic) UIView *headerView;
@end

itemClickedAtPoint:方法用来响应item的点击手势,reloadData方法用来重新加载CollectionView,getItemAtPoint:方法用来根据point获取item对象。然后是两个委托(delegate,datasource)的详细定义:

#pragma mark -
#pragma mark 委托
@protocol iCollectionDataSource<NSObject>
@required
-(NSInteger)numberOfItemsInCollection;
-(NSInteger)numberOfItemsInRow;
@optional
-(NSInteger)numberofMore;
@end

@protocol iCollectionDelegate<NSObject>
@required
-(iCollectionItem *)itemInCollectionAtPoint:(CGPoint)point collectionView:(iCollectionView *)collection;
-(CGSize)itemSizeInCollection;//item的大小
@optional
-(void)itemDidSelectedAtPoint:(CGPoint)point;//item的点击响应事件
-(BOOL)isNeedRefreshOrMore;//是否需要添加刷新、更多
-(void)doCollectionRefresh;//执行刷新事件
-(void)doCollectionMore;//执行更多加载事件

-(UIView *)collectionViewForHeader;//headerView
-(CGFloat)spliteWidth;//item之间的分隔距离
-(CGFloat)marginsLength;//item的边距
@end

接下来是.m中的具体实现,首先引入头文件:

#import "iCollectionView.h"
#import "iCollectionItem.h"
#import "BaseRMView.h"//刷新、更多

然后定义一些“私有”变量:

@interface iCollectionView()
@property (strong, nonatomic) NSMutableDictionary *contentItemDictionary;/*cache*/
@property (assign,nonatomic) NSInteger showCount;
@property (assign,nonatomic) NSInteger offRowIndex;
@property (assign,nonatomic) CGFloat itemSpliteWidth;
@property (assign,nonatomic) NSInteger rows;

@property (assign, nonatomic) NSInteger numberOfItemsInCollection;
@property (assign,nonatomic) NSInteger numberOfItemsInRow;
@property (assign, nonatomic) CGFloat heightOfRow;

@property (assign, nonatomic) CGRect viewFrame;
@property (assign,nonatomic) BOOL isFirstLoad;
@property (assign,nonatomic) CGFloat lastOffsetY;
@property (assign,nonatomic) NSInteger lastRowIndex;
@property (assign,nonatomic) NSInteger topRowIndex;

@property (assign,nonatomic) NSInteger numberOfMore;

@property (assign,nonatomic) BOOL isNeedShowMoreTag;
@property (strong,nonatomic) BaseRMView *refreshView;
@property (strong,nonatomic) BaseRMView *moreView;

@property (assign,nonatomic) CGFloat baseOffsetY;
@property (assign,nonatomic) CGFloat baseCanMove;

@property (assign,nonatomic) NSInteger beforeRowCount;

@property (assign,nonatomic) CGSize itemSize;
@property (assign,nonatomic) CGFloat marginsLength;

//@property (assign,nonatomic) NSInteger firstShowCount;
@end

然后是页面的初始化:

#pragma mark -
#pragma mark 页面初始化
-(id)init{
    CGRect frame=[UIScreen mainScreen].applicationFrame;
    self=[self initWithFrame:frame];
    if(self){

    }
    return self;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        _viewFrame=frame;
        self.delegate=self;
        _isFirstLoad=YES;
        _contentItemDictionary=[[NSMutableDictionary alloc] init];
        _isNeedShowMoreTag=NO;
    }
    return self;
}

然后是数据的初始化:

#pragma mark -
#pragma mark 数据初始化
-(void)loadData{
    if ([_dataSource respondsToSelector:@selector(numberOfItemsInCollection)]) {
        _numberOfItemsInCollection=[_dataSource numberOfItemsInCollection];
    }else{
        _numberOfItemsInCollection=0;
    }
    if([_dataSource respondsToSelector:@selector(numberOfItemsInRow)]){
        _numberOfItemsInRow=[_dataSource numberOfItemsInRow];
        _heightOfRow=((320-10-10-(_numberOfItemsInRow-1)*10)/_numberOfItemsInRow);
        _itemSpliteWidth=10;
    }else{
        _numberOfItemsInRow=3;//默认为3
        _heightOfRow=88;
        _itemSpliteWidth=18;
    }
    if ([_dataSource respondsToSelector:@selector(numberofMore)]) {
        _numberOfMore=[_dataSource numberofMore];
    }
    if ([_customDelegate respondsToSelector:@selector(isNeedRefreshOrMore)]) {
        _isNeedShowMoreTag=[_customDelegate isNeedRefreshOrMore];
    }
    if ([_customDelegate respondsToSelector:@selector(collectionViewForHeader)]) {
        _headerView=[_customDelegate collectionViewForHeader];
        if (![self.subviews containsObject:_headerView]) {
            [self addSubview:_headerView];
        }
    }

    if ([_customDelegate respondsToSelector:@selector(itemSizeInCollection)]) {
        CGSize itemSize=[_customDelegate itemSizeInCollection];
        _itemSize=itemSize;
    }
    if ([_customDelegate respondsToSelector:@selector(spliteWidth)]) {
        _itemSpliteWidth=[_customDelegate spliteWidth];
    }else{
        _itemSpliteWidth=10;
    }
    if ([_customDelegate respondsToSelector:@selector(marginsLength)]) {
        _marginsLength=[_customDelegate marginsLength];
    }else{
        _marginsLength=10;
    }

    _rows=ceil((float)_numberOfItemsInCollection/_numberOfItemsInRow);
    CGFloat contentHeight=(_rows*_itemSize.height + (_rows+1)*_itemSpliteWidth+_headerView.frame.size.height);
    CGFloat scrollContentHeight=contentHeight>_viewFrame.size.height?
                            contentHeight : _viewFrame.size.height;
    [self setContentSize:CGSizeMake(_viewFrame.size.width, scrollContentHeight)];

    _showCount=  (NSInteger)ceil((self.frame.size.height/(_itemSize.height +10)));
    if (_rows!=0) {
        if (self.contentOffset.y<_headerView.frame.size.height) {
            _topRowIndex=0;
            CGFloat offSetY=self.contentOffset.y<0?0:self.contentOffset.y;
            _lastRowIndex=(_viewFrame.size.height-_headerView.frame.size.height+offSetY)/(_itemSize.height +_itemSpliteWidth);
        }else{
            _topRowIndex=(self.contentOffset.y-_headerView.frame.size.height)/(_itemSize.height +_itemSpliteWidth);
            _lastRowIndex=(_viewFrame.size.height-_headerView.frame.size.height+self.contentOffset.y)/(_itemSize.height +_itemSpliteWidth);
        }
        for (int i=_topRowIndex; i<_lastRowIndex+1; i++) {
            [self creatItem:i];
        }
    }else{
        for (UIView *subView in self.subviews) {
            [subView removeFromSuperview];
        }
    }

    if (_isNeedShowMoreTag==YES) {
        if (![self.subviews containsObject:_refreshView]) {
            _refreshView=[[BaseRMView alloc] initWithState:Refresh];
            [_refreshView setFrame:CGRectMake(0, -50, 320, 50)];
            [_refreshView setBackgroundColor:[UIColor grayColor]];
            [self addSubview:_refreshView];
        }
        if (![self.subviews containsObject:_moreView]) {
            _moreView=[[BaseRMView alloc] initWithState:More];
            [_moreView setFrame:CGRectMake(0, self.contentSize.height, 320, 50)];
            [_moreView setBackgroundColor:[UIColor grayColor]];
            [self addSubview:_moreView];
        }else{
            [_moreView setFrame:CGRectMake(0, self.contentSize.height, 320, 50)];
        }
    }
}

在这里我们获取了item的个数、每一行中item的个数、每一个item的大小、item之间的分隔距离、item的边距,以及计算除了总行数、view中能够现实的item行数(showCount)、设置了ScrollView的滚动大小(contentSize、初始化了topIndex(当前显示的最上一行index)与lastIndex(当前显示的最下一行index),在最后初始化了刷新与加载的view。

    原文作者:EscapedDog
    原文地址: https://segmentfault.com/a/1190000000321372
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞