【OC】【一秒就会】【collectionView 头部吸住功能】
生活随笔
收集整理的這篇文章主要介紹了
【OC】【一秒就会】【collectionView 头部吸住功能】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
為什么80%的碼農都做不了架構師?>>> ??
貢獻作者 -【XJDomain】
博客XJ:? https://my.oschina.net/shengbingli/blog
GitHub:? https://github.com/lishengbing/XJQRCodeToolDemo
直接使用我的自定義類:
1:tableview有自動頭部和底部吸頂的功能,collectionView也是可以做到的
2:將collectionView的 flowLayout 換成我的自定義類的對象即可
使用范例:
//固定頭部layout SectionHeadercCollectionViewLayout *layout = [[SectionHeadercCollectionViewLayout alloc] init];//不固定頭部 UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];?
// // SectionHeadercCollectionViewLayout.h // XDSectionCollectionView // // Created by 李勝兵 on 15/9/9. // Copyright (c) 2015年 李勝兵. All rights reserved. //#import <UIKit/UIKit.h>@interface SectionHeadercCollectionViewLayout : UICollectionViewFlowLayout@end?
// // SectionHeadercCollectionViewLayout.m // XDSectionCollectionView // // Created by 李勝兵 on 15/9/9. // Copyright (c) 2015年 李勝兵. All rights reserved. //#import "SectionHeadercCollectionViewLayout.h"/*** SectionHeader可以像tableView那樣懸浮在頂部* 繼承于UICollectionViewFlowLayout,用法與collectionViewFlowLayout一樣*/ @implementation SectionHeadercCollectionViewLayout- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {//UICollectionViewLayoutAttributes:我稱它為collectionView中的item(包括cell和header、footer這些)的《結構信息》//截取到父類所返回的數組(里面放的是當前屏幕所能展示的item的結構信息),并轉化成不可變數組NSMutableArray *superArray = [[super layoutAttributesForElementsInRect:rect] mutableCopy];//創建存索引的數組,無符號(正整數),無序(不能通過下標取值),不可重復(重復的話會自動過濾)NSMutableIndexSet *noneHeaderSections = [NSMutableIndexSet indexSet];//遍歷superArray,得到一個當前屏幕中所有的section數組for (UICollectionViewLayoutAttributes *attributes in superArray){//如果當前的元素分類是一個cell,將cell所在的分區section加入數組,重復的話會自動過濾if (attributes.representedElementCategory == UICollectionElementCategoryCell){[noneHeaderSections addIndex:attributes.indexPath.section];}}//遍歷superArray,將當前屏幕中擁有的header的section從數組中移除,得到一個當前屏幕中沒有header的section數組//正常情況下,隨著手指往上移,header脫離屏幕會被系統回收而cell尚在,也會觸發該方法for (UICollectionViewLayoutAttributes *attributes in superArray){//如果當前的元素是一個header,將header所在的section從數組中移除if ([attributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]){[noneHeaderSections removeIndex:attributes.indexPath.section];}}//遍歷當前屏幕中沒有header的section數組[noneHeaderSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop){//取到當前section中第一個item的indexPathNSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:idx];//獲取當前section在正常情況下已經離開屏幕的header結構信息UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];//如果當前分區確實有因為離開屏幕而被系統回收的headerif (attributes){//將該header結構信息重新加入到superArray中去[superArray addObject:attributes];}}];//遍歷superArray,改變header結構信息中的參數,使它可以在當前section還沒完全離開屏幕的時候一直顯示for (UICollectionViewLayoutAttributes *attributes in superArray) {//如果當前item是headerif ([attributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]){//得到當前header所在分區的cell的數量NSInteger numberOfItemsInSection = [self.collectionView numberOfItemsInSection:attributes.indexPath.section];//得到第一個item的indexPathNSIndexPath *firstItemIndexPath = [NSIndexPath indexPathForItem:0 inSection:attributes.indexPath.section];//得到最后一個item的indexPathNSIndexPath *lastItemIndexPath = [NSIndexPath indexPathForItem:MAX(0, numberOfItemsInSection-1) inSection:attributes.indexPath.section];//得到第一個item和最后一個item的結構信息UICollectionViewLayoutAttributes *firstItemAttributes, *lastItemAttributes;if (numberOfItemsInSection>0){//cell有值,則獲取第一個cell和最后一個cell的結構信息firstItemAttributes = [self layoutAttributesForItemAtIndexPath:firstItemIndexPath];lastItemAttributes = [self layoutAttributesForItemAtIndexPath:lastItemIndexPath];}else{//cell沒值,就新建一個UICollectionViewLayoutAttributesfirstItemAttributes = [UICollectionViewLayoutAttributes new];//然后模擬出在當前分區中的唯一一個cell,cell在header的下面,高度為0,還與header隔著可能存在的sectionInset的topCGFloat y = CGRectGetMaxY(attributes.frame)+self.sectionInset.top;firstItemAttributes.frame = CGRectMake(0, y, 0, 0);//因為只有一個cell,所以最后一個cell等于第一個celllastItemAttributes = firstItemAttributes;}//獲取當前header的frameCGRect rect = attributes.frame;//當前的滑動距離 + 因為導航欄產生的偏移量,默認為64(如果app需求不同,需自己設置)CGFloat offset = self.collectionView.contentOffset.y;//第一個cell的y值 - 當前header的高度 - 可能存在的sectionInset的topCGFloat headerY = firstItemAttributes.frame.origin.y - rect.size.height - self.sectionInset.top;//哪個大取哪個,保證header懸停//針對當前header基本上都是offset更加大,針對下一個header則會是headerY大,各自處理CGFloat maxY = MAX(offset,headerY);//最后一個cell的y值 + 最后一個cell的高度 + 可能存在的sectionInset的bottom - 當前header的高度//當當前section的footer或者下一個section的header接觸到當前header的底部,計算出的headerMissingY即為有效值CGFloat headerMissingY = CGRectGetMaxY(lastItemAttributes.frame) + self.sectionInset.bottom - rect.size.height;//給rect的y賦新值,因為在最后消失的臨界點要跟誰消失,所以取小rect.origin.y = MIN(maxY,headerMissingY);//給header的結構信息的frame重新賦值attributes.frame = rect;//如果按照正常情況下,header離開屏幕被系統回收,而header的層次關系又與cell相等,如果不去理會,會出現cell在header上面的情況//通過打印可以知道cell的層次關系zIndex數值為0,我們可以將header的zIndex設置成1,如果不放心,也可以將它設置成非常大,這里隨便填了個7attributes.zIndex = 7;}}//轉換回不可變數組,并返回return [superArray copy];}//return YES;表示一旦滑動就實時調用上面這個layoutAttributesForElementsInRect:方法 - (BOOL) shouldInvalidateLayoutForBoundsChange:(CGRect)newBound {return YES; }@end?
如果你覺得對你有用,請你star,謝謝
如果你覺得以后對你還是有點用,也請你star、謝謝
// 強大的二維碼一鍵搞定
https://github.com/lishengbing/XJQRCodeToolDemo
// 強大的swift3.0版本側滑全功能、第三方庫都滿足不了我的要求
https://github.com/lishengbing/swift3.0-XJDragerDemo
// 強大的oc版本抽屜效果、第三方庫都滿足不了我的要求
https://github.com/lishengbing/XJDragViewController
轉載于:https://my.oschina.net/shengbingli/blog/793416
總結
以上是生活随笔為你收集整理的【OC】【一秒就会】【collectionView 头部吸住功能】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JWT实现token-based会话管理
- 下一篇: linux 用户/用户组添加修改删除(u