確定你會(huì)使用UICollectionView?三個(gè)案列顛覆你的認(rèn)知

UICollectionView是針對(duì)IOS6 以后才能使用的控件,比起UITableView來(lái)說(shuō)功能更強(qiáng)大,使用起來(lái)更方便,使用UICollectionView也可以完全取代UITableView。UICollectionView最重要的一點(diǎn)就是加載設(shè)置UICollectionViewFlowLayout。接下來(lái)就用三個(gè)demo來(lái)展示一下UICollectionView 的強(qiáng)大,對(duì)于iOS開(kāi)發(fā)進(jìn)階還是有比較大的幫助的。

Demo下載鏈接:https://github.com/ZhengYaWei1992/ZWAdvanceCollectionView

第一個(gè)效果圖是UICollectionViewCell的拖動(dòng),刪除,之前開(kāi)發(fā)一個(gè)項(xiàng)目中主頁(yè)面的布局自定義排版使用過(guò)這個(gè)功能,所以給整理了下。

第二個(gè)效果圖是一個(gè)輕量級(jí)別的仿蘋果的Cover Flow效果。主要實(shí)現(xiàn)是基于自定義布局的調(diào)整

第三個(gè)效果圖需要你仔細(xì)看一下。重點(diǎn)并不是聯(lián)動(dòng),重點(diǎn)在于效果圖中右側(cè)UICollectionView組頭是隨著當(dāng)前界面展示的section而浮動(dòng)在界面上。效果看起來(lái)簡(jiǎn)單,實(shí)際上要想實(shí)現(xiàn),設(shè)計(jì)的邏輯判斷不是那么簡(jiǎn)單的。在UITableView上這個(gè)效果很好實(shí)現(xiàn),只需要設(shè)置UITableViewStylePlain,想進(jìn)一步了解UITableView中的組頭浮動(dòng)相關(guān)內(nèi)容請(qǐng)參照我之前寫過(guò)的一篇文章:http://www.lxweimin.com/p/3b6d9a340e59

看效果圖啦,看效果圖啦,看效果圖啦,看效果圖啦,看效果圖啦。

效果圖一:cell的手勢(shì)拖動(dòng)移動(dòng)
效果圖二:蘋果的coverFlow效果
效果圖二:浮動(dòng)組頭

接下來(lái)就一個(gè)一個(gè)看啦。

1、UICollectionViewCell的移動(dòng)。

這個(gè)很簡(jiǎn)單,但是要重點(diǎn)說(shuō)明一點(diǎn)。如果將長(zhǎng)按手勢(shì)添加到cell上手勢(shì)不是很靈敏。解決的方法:將長(zhǎng)按手勢(shì)添加到self.collectionView上即可.

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    NSArray *arr = @[@"手機(jī)充值", @"親民金融", @"就業(yè)招聘", @"鄉(xiāng)間旅游",@"鄉(xiāng)村醫(yī)療", @"違章查詢", @"生活服務(wù)", @"鄉(xiāng)村名宿",@"新農(nóng)頭條"];
    self.array = [NSMutableArray arrayWithArray:arr];
    _longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(lonePressMoving:)];
    [self.collectionView addGestureRecognizer:_longPress];
    [self.view addSubview:self.collectionView];
}

長(zhǎng)按手勢(shì)實(shí)現(xiàn)。

- (void)lonePressMoving:(UILongPressGestureRecognizer *)longPress{
    switch (longPress.state) {
        case UIGestureRecognizerStateBegan:{//開(kāi)始
            {
                //獲取長(zhǎng)按的cell
                NSIndexPath *selectIndexPath = [self.collectionView indexPathForItemAtPoint:[_longPress locationInView:self.collectionView]];
                CollectionViewCell *cell = (CollectionViewCell *)[self.collectionView cellForItemAtIndexPath:selectIndexPath];
                //顯示cell上的刪除按鈕
                [cell.deleteButton setHidden:NO];
                cell.deleteButton.tag = selectIndexPath.item;
                //給當(dāng)前cell上的刪除按鈕添加點(diǎn)擊事件
                [cell.deleteButton addTarget:self action:@selector(deleteButtonClick:) forControlEvents:UIControlEventTouchUpInside];
                //設(shè)置collectionView開(kāi)始移動(dòng)
                [_collectionView beginInteractiveMovementForItemAtIndexPath:selectIndexPath];
            }
            break;
        }
        case UIGestureRecognizerStateChanged:{//拖動(dòng)中
             [self.collectionView updateInteractiveMovementTargetPosition:[longPress locationInView:_longPress.view]];
            break;
        }
        case UIGestureRecognizerStateEnded:{//結(jié)束
            
             [self.collectionView endInteractiveMovement];
            break;
        }
        default:
            [self.collectionView cancelInteractiveMovement];
            break;
    }
}

刪除cell代碼實(shí)現(xiàn)。

- (void)deleteButtonClick:(UIButton *)deleteBtn{
    //cell的隱藏刪除設(shè)置
    NSIndexPath *selectIndexPath = [self.collectionView indexPathForItemAtPoint:[_longPress locationInView:self.collectionView]];
    // 找到當(dāng)前的cell
    CollectionViewCell *cell = (CollectionViewCell *)[self.collectionView cellForItemAtIndexPath:selectIndexPath];
    cell.deleteButton.hidden = NO;
    //取出源item數(shù)據(jù)
    id objc = [self.array objectAtIndex:deleteBtn.tag];
    //從資源數(shù)組中移除該數(shù)據(jù)
    [self.array removeObject:objc];
    [self.collectionView reloadData];
}

要實(shí)現(xiàn)的代理方法以及特別注意的事項(xiàng),具體代碼中有說(shuō)明。重點(diǎn)注意第四個(gè)代理方法的實(shí)現(xiàn)。

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    return self.array.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath];
    cell.lable.text = self.array[indexPath.item];
    cell.deleteButton.hidden = YES;
    return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
    ViewController2 *vc = [[ViewController2 alloc]init];
    [self.navigationController pushViewController:vc animated:YES];
   
}
//交換collectionView必須要實(shí)現(xiàn)的代理方法
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(nonnull NSIndexPath *)sourceIndexPath toIndexPath:(nonnull NSIndexPath *)destinationIndexPath{
    NSIndexPath *selectIndexPath = [self.collectionView indexPathForItemAtPoint:[_longPress locationInView:self.collectionView]];
    // 找到當(dāng)前的cell
    CollectionViewCell *cell = (CollectionViewCell *)[self.collectionView cellForItemAtIndexPath:selectIndexPath];
    cell.deleteButton.hidden = YES;
    
    /*1.存在的問(wèn)題,移動(dòng)是二個(gè)一個(gè)移動(dòng)的效果*/
    //  [collectionView moveItemAtIndexPath:sourceIndexPath toIndexPath:destinationIndexPath];
    /*2.存在的問(wèn)題:只是交換而不是移動(dòng)的效果*/
    //    [self.array exchangeObjectAtIndex:sourceIndexPath.item withObjectAtIndex:destinationIndexPath.item];
    /*3.完整的解決效果*/
    //取出源item數(shù)據(jù)
    id objc = [self.array objectAtIndex:sourceIndexPath.item];
    //從資源數(shù)組中移除該數(shù)據(jù)
    [self.array removeObject:objc];
    //將數(shù)據(jù)插入到資源數(shù)組中的目標(biāo)位置上
    [self.array insertObject:objc atIndex:destinationIndexPath.item];

    [self.collectionView reloadData];
}

2、仿蘋果Cover Flow效果。

2.1、自定義流式布局

這個(gè)效果的實(shí)現(xiàn)和第三個(gè)小何的實(shí)現(xiàn)核心在于自定義流式布局(UICollectionViewFlowLayout),涉及UICollectionView相關(guān)實(shí)心只要按照常規(guī)布局即可,只是在在設(shè)置布局的時(shí)候更改為自定義布局,這個(gè)自定義布局應(yīng)該繼承于UICollectionViewFlowLayout。如下代碼,ZWCoverFlowLayout是繼承與UICollectionViewFlowLayout的自定義類。

ZWCoverFlowLayout *layout = [[ZWCoverFlowLayout alloc] init];
        //水平方向,元素之間的最小距離
        layout.minimumInteritemSpacing = 0;
        //行之間的最小距離
        layout.minimumLineSpacing = 20;
        layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
        //設(shè)置元素的大小
        UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, 150) collectionViewLayout:layout];
2.2、重寫三個(gè)重要的系統(tǒng)方法。

最重要的是看自定義流式布局類的代碼實(shí)現(xiàn)。在這個(gè)自定義類中我們要重寫系統(tǒng)的三個(gè)方法。三個(gè)方法的作用以及參數(shù)說(shuō)明如下:
設(shè)置布局屬性。

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;

當(dāng)bounds發(fā)生變化的時(shí)候是否需要重新布局

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
    //是否可以隨著collectionView的滾動(dòng)而變化
    return YES;
}

這個(gè)方法主要是為了停止?jié)L動(dòng)的時(shí)候,讓一個(gè)cell顯示到正中間
返回值:當(dāng)停止?jié)L動(dòng)的時(shí)候,人為停止的位置
參一:當(dāng)停止?jié)L動(dòng)的時(shí)候,自然情況下根據(jù)“慣性”停留的位置
參二:每秒滾動(dòng)多少個(gè)點(diǎn)

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
2.3、具體實(shí)現(xiàn)代碼。

設(shè)置布局屬性方法的實(shí)現(xiàn)。說(shuō)明:每個(gè)cell唯一對(duì)應(yīng)一個(gè)attribute對(duì)象,根據(jù)獲取到的attribute對(duì)象我們可以直接設(shè)置每個(gè)cell的縮放布局等。

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
    //1、獲取cell對(duì)應(yīng)的attributes對(duì)象   每個(gè)cell唯一對(duì)應(yīng)一個(gè)attribute對(duì)象
    NSArray *arrayAttrs = [super layoutAttributesForElementsInRect:rect];
    //計(jì)算整體的中心點(diǎn)的x值
    CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.bounds.size.width * 0.5;
    //2、修改attributes對(duì)象
    for (UICollectionViewLayoutAttributes *attr in arrayAttrs) {
        //計(jì)算每個(gè)cell和中心點(diǎn)的具體
        CGFloat distance = ABS(attr.center.x - centerX);
        //距離越大,縮放比越小,距離越小,縮放比越大
        //縮放因子
        CGFloat factor = 0.003;
        CGFloat scale = 1 / (1 + distance * factor);
        attr.transform = CGAffineTransformMakeScale(scale, scale);
    }
    return arrayAttrs;
}

當(dāng)bounds發(fā)生變化的時(shí)候是否需要重新布局

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
    //是否可以隨著collectionView的滾動(dòng)而變化
    return YES;
}

這個(gè)方法主要是為了停止?jié)L動(dòng)的時(shí)候,讓一個(gè)特定cell顯示到正中間,哪一個(gè)cell距離UICollectionView的中心比較近,就將哪一個(gè)cell顯示到中間。

//返回值:當(dāng)停止?jié)L動(dòng)的時(shí)候,人為停止的位置
//參一:當(dāng)停止?jié)L動(dòng)的時(shí)候,自然情況下根據(jù)“慣性”停留的位置
//參二:每秒滾動(dòng)多少個(gè)點(diǎn)
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{
    //計(jì)算整體的中心點(diǎn)的值
    CGFloat centerX = proposedContentOffset.x + self.collectionView.bounds.size.width * 0.5;
    //這里不能使用contentOffset.x 因?yàn)槭种敢惶饋?lái),contentOffset.x就不會(huì)再變化,按照慣性滾動(dòng)的不會(huì)被計(jì)算到其中
    //CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.bounds.size.width * 0.5;
    
    //計(jì)算可視區(qū)域
    CGFloat visibleX = proposedContentOffset.x;
    CGFloat visibleY = proposedContentOffset.y;
    CGFloat visibleW = self.collectionView.bounds.size.width;
    CGFloat visibleH = self.collectionView.bounds.size.height;
    //獲取可視區(qū)域cell對(duì)應(yīng)的attributes對(duì)象   每個(gè)cell唯一對(duì)應(yīng)一個(gè)attribute對(duì)象
    NSArray *arrayAttrs = [super layoutAttributesForElementsInRect:CGRectMake(visibleX, visibleY, visibleW, visibleH)];
    
    //比較出最小的偏移
    int minIdx = 0;//假設(shè)最小的下標(biāo)是0
    UICollectionViewLayoutAttributes *minAttr = arrayAttrs[minIdx];
    //循環(huán)比較出最小的
    for(int i = 1; i < arrayAttrs.count; i++){
        //計(jì)算兩個(gè)距離
        //1、minAttr和中心點(diǎn)的距離
        CGFloat distance1 = ABS(minAttr.center.x - centerX);
        //2、計(jì)算出當(dāng)前循環(huán)的attr對(duì)象和centerX的距離
        UICollectionViewLayoutAttributes *obj = arrayAttrs[i];
        CGFloat distance2 = obj.center.x - centerX;
        //3、比較
        if (distance2 < distance1) {
            minIdx = i;
            minAttr = obj;
        }
    }
    
    //計(jì)算出最小的偏移值
    CGFloat offsetX = minAttr.center.x - centerX;
    return CGPointMake(offsetX + proposedContentOffset.x, proposedContentOffset.y);
}

到此就OK了,如果還想擴(kuò)充更多的,只要在樣式上進(jìn)行簡(jiǎn)單的調(diào)整即可。如翻轉(zhuǎn)、拉升、動(dòng)畫效果等。

3、UICollectionView的組頭浮動(dòng)。

其實(shí)這個(gè)效果的實(shí)現(xiàn),代碼量不是很多,但是在邏輯處理上還是需要考慮很多的。所以下面的代碼中,我會(huì)把每一步要做的事都用語(yǔ)言完全描述清楚。
#######3、1 需要重寫的系統(tǒng)方法
這個(gè)效果的實(shí)現(xiàn),和第二個(gè)Cover Flow效果一樣,同樣需要自定義流式布局。需要重寫系統(tǒng)的兩個(gè)方法。

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;

return YES:表示一旦滑動(dòng)就實(shí)時(shí)調(diào)用上面這個(gè)layoutAttributesForElementsInRect:方法

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBound{
    return YES;
}

#######3、2 具體實(shí)現(xiàn)代碼

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
    // UICollectionViewLayoutAttributes:我稱它為collectionView中的item(包括cell和header、footer這些)的《結(jié)構(gòu)信息》
    // 截取到父類所返回的數(shù)組(里面放的是當(dāng)前屏幕所能展示的item的結(jié)構(gòu)信息),并轉(zhuǎn)化成不可變數(shù)組
    NSMutableArray *superArray = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
    // 創(chuàng)建存索引的數(shù)組,無(wú)符號(hào)(正整數(shù)),無(wú)序(不能通過(guò)下標(biāo)取值),不可重復(fù)(重復(fù)的話會(huì)自動(dòng)過(guò)濾)
    NSMutableIndexSet *noneHeaderSections = [NSMutableIndexSet indexSet];
    
    // 遍歷superArray,得到一個(gè)當(dāng)前屏幕中所有的section數(shù)組
    for (UICollectionViewLayoutAttributes *attributes in superArray){
        //如果當(dāng)前的元素分類是一個(gè)cell,將cell所在的分區(qū)section加入數(shù)組,重復(fù)的話會(huì)自動(dòng)過(guò)濾
        if (attributes.representedElementCategory == UICollectionElementCategoryCell){
            [noneHeaderSections addIndex:attributes.indexPath.section];
        }
    }
    
    // 遍歷superArray,將當(dāng)前屏幕中擁有的header的section從數(shù)組中移除,得到一個(gè)當(dāng)前屏幕中沒(méi)有header的section數(shù)組
    // 正常情況下,隨著手指往上移,header脫離屏幕會(huì)被系統(tǒng)回收而cell尚在,也會(huì)觸發(fā)該方法
    for (UICollectionViewLayoutAttributes *attributes in superArray){
        // 如果當(dāng)前的元素是一個(gè)header,將header所在的section從數(shù)組中移除
        if ([attributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]){
            [noneHeaderSections removeIndex:attributes.indexPath.section];
        }
    }
    
    // 遍歷當(dāng)前屏幕中沒(méi)有header的section數(shù)組
    [noneHeaderSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *_Nonnull stop) {
        // 取到當(dāng)前section中第一個(gè)item的indexPath
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:idx];
        // 獲取當(dāng)前section在正常情況下已經(jīng)離開(kāi)屏幕的header結(jié)構(gòu)信息
        UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];
        // 如果當(dāng)前分區(qū)確實(shí)有因?yàn)殡x開(kāi)屏幕而被系統(tǒng)回收的header
        if (attributes){
            // 將該header結(jié)構(gòu)信息重新加入到superArray中去
            [superArray addObject:attributes];
        }
    }];
    // 遍歷superArray,改變header結(jié)構(gòu)信息中的參數(shù),使它可以在當(dāng)前section還沒(méi)完全離開(kāi)屏幕的時(shí)候一直顯示
    for (UICollectionViewLayoutAttributes *attributes in superArray){
        // 如果當(dāng)前item是header
        if ([attributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]){
            // 得到當(dāng)前header所在分區(qū)的cell的數(shù)量
            NSInteger numberOfItemsInSection = [self.collectionView numberOfItemsInSection:attributes.indexPath.section];
            // 得到第一個(gè)item的indexPath
            NSIndexPath *firstItemIndexPath = [NSIndexPath indexPathForItem:0 inSection:attributes.indexPath.section];
            // 得到最后一個(gè)item的indexPath
            NSIndexPath *lastItemIndexPath = [NSIndexPath indexPathForItem:MAX(0, numberOfItemsInSection - 1) inSection:attributes.indexPath.section];
            // 得到第一個(gè)item和最后一個(gè)item的結(jié)構(gòu)信息
            UICollectionViewLayoutAttributes *firstItemAttributes, *lastItemAttributes;
            if (numberOfItemsInSection > 0){
                // cell有值,則獲取第一個(gè)cell和最后一個(gè)cell的結(jié)構(gòu)信息
                firstItemAttributes = [self layoutAttributesForItemAtIndexPath:firstItemIndexPath];
                lastItemAttributes = [self layoutAttributesForItemAtIndexPath:lastItemIndexPath];
            }else{
                // cell沒(méi)值,就新建一個(gè)UICollectionViewLayoutAttributes
                firstItemAttributes = [UICollectionViewLayoutAttributes new];
                // 然后模擬出在當(dāng)前分區(qū)中的唯一一個(gè)cell,cell在header的下面,高度為0,還與header隔著可能存在的sectionInset的top
                CGFloat y = CGRectGetMaxY(attributes.frame) + self.sectionInset.top;
                firstItemAttributes.frame = CGRectMake(0, y, 0, 0);
                // 因?yàn)橹挥幸粋€(gè)cell,所以最后一個(gè)cell等于第一個(gè)cell
                lastItemAttributes = firstItemAttributes;
            }
            
            // 獲取當(dāng)前header的frame
            CGRect rect = attributes.frame;
            // 當(dāng)前的滑動(dòng)距離 + 因?yàn)閷?dǎo)航欄產(chǎn)生的偏移量,默認(rèn)為64(如果app需求不同,需自己設(shè)置)
            CGFloat offset = self.collectionView.contentOffset.y + _navHeight;
            // 第一個(gè)cell的y值 - 當(dāng)前header的高度 - 可能存在的sectionInset的top
            CGFloat headerY = firstItemAttributes.frame.origin.y - rect.size.height - self.sectionInset.top;
            // 哪個(gè)大取哪個(gè),保證header懸停
            // 針對(duì)當(dāng)前header基本上都是offset更加大,針對(duì)下一個(gè)header則會(huì)是headerY大,各自處理
            CGFloat maxY = MAX(offset, headerY);
            // 最后一個(gè)cell的y值 + 最后一個(gè)cell的高度 + 可能存在的sectionInset的bottom - 當(dāng)前header的高度
            // 當(dāng)當(dāng)前section的footer或者下一個(gè)section的header接觸到當(dāng)前header的底部,計(jì)算出的headerMissingY即為有效值
            CGFloat headerMissingY = CGRectGetMaxY(lastItemAttributes.frame) + self.sectionInset.bottom - rect.size.height;
            // 給rect的y賦新值,因?yàn)樵谧詈笙У呐R界點(diǎn)要跟誰(shuí)消失,所以取小
            rect.origin.y = MIN(maxY, headerMissingY);
            // 給header的結(jié)構(gòu)信息的frame重新賦值
            attributes.frame = rect;
            // 如果按照正常情況下,header離開(kāi)屏幕被系統(tǒng)回收,而header的層次關(guān)系又與cell相等,如果不去理會(huì),會(huì)出現(xiàn)cell在header上面的情況
            // 通過(guò)打印可以知道cell的層次關(guān)系z(mì)Index數(shù)值為0,我們可以將header的zIndex設(shè)置成1,如果不放心,也可以將它設(shè)置成非常大,這里隨便填了個(gè)7
            attributes.zIndex = 7;
        }
    }
    // 轉(zhuǎn)換回不可變數(shù)組,并返回
    return [superArray copy];
}


// return YES:表示一旦滑動(dòng)就實(shí)時(shí)調(diào)用上面這個(gè)layoutAttributesForElementsInRect:方法
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBound{
    return YES;
}

#######3、2 layoutAttributesForElementsInRect:方法代碼實(shí)現(xiàn)思路總結(jié)。
說(shuō)明:superArray是截取到父類所返回的數(shù)組(里面放的是當(dāng)前屏幕所能展示的item的結(jié)構(gòu)信息)
1、遍歷superArray,得到一個(gè)當(dāng)前屏幕中所有的section數(shù)組
2、遍歷superArray,將當(dāng)前屏幕中擁有的header的section從數(shù)組中移除,得到一個(gè)當(dāng)前屏幕中沒(méi)有header的section數(shù)組
3、遍歷當(dāng)前屏幕中沒(méi)有header的section數(shù)組,如果當(dāng)前分區(qū)確實(shí)有因?yàn)殡x開(kāi)屏幕而被系統(tǒng)回收的header,將該header結(jié)構(gòu)信息重新加入到superArray中去。
4、遍歷superArray,改變header結(jié)構(gòu)信息中的參數(shù),使它可以在當(dāng)前section還沒(méi)完全離開(kāi)屏幕的時(shí)候一直顯示。這一步里面處理的邏輯是相對(duì)比較麻煩的,要獲取到同個(gè)分組中最后一個(gè)和第一個(gè)item,然后根據(jù)區(qū)分上滾和下滾控制浮動(dòng)組頭的顯示和隱藏。

另外還有注意一個(gè)問(wèn)題:
如果按照正常情況下,header離開(kāi)屏幕被系統(tǒng)回收,而header的層次關(guān)系又與cell相等,如果不去理會(huì),會(huì)出現(xiàn)cell在header上面的情況。所以這里要設(shè)置浮動(dòng)組頭的zIndex屬性,保證其顯示在最上方。

到此,針對(duì)UICollectionView的浮動(dòng)組頭jiu'shi'xian

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,538評(píng)論 3 417
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 176,423評(píng)論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 62,991評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,761評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,207評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,419評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,959評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,782評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,983評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,222評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 34,653評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 35,901評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,678評(píng)論 3 392
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,978評(píng)論 2 374

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,151評(píng)論 4 61
  • 問(wèn)答題47 /72 常見(jiàn)瀏覽器兼容性問(wèn)題與解決方案? 參考答案 (1)瀏覽器兼容問(wèn)題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,776評(píng)論 1 92
  • 前言 iOS里的UI控件其實(shí)沒(méi)有幾個(gè),界面基本就是圍繞那么幾個(gè)控件靈活展開(kāi),最難的應(yīng)屬UICollectionVi...
    alenpaulkevin閱讀 31,948評(píng)論 9 176
  • 十年前,無(wú)聊翻看國(guó)家地圖,策劃了這條驢行之路。那年,西塘沒(méi)有門票,人也不太多,酒吧也就幾家,純樸的水鄉(xiāng)讓我心醉。于...
    亞當(dāng)沒(méi)夏娃閱讀 702評(píng)論 0 0
  • 走在嘈雜聲的路上,心都跟著累,在這種密集的城中村里,縱然難得的一天假期,依然找不到讓心靈得到放的那么一塊塊地方!
    初夏陽(yáng)光li閱讀 152評(píng)論 0 0