[iOS]自定義UICollectionView 2-1–CollectionView的實現(定義與初始化)

EscapedDog發表於2013-10-17

我廠廣招各路大神加入: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。

相關文章