五个UICollectionView常用的知识点

栏目: IOS · 发布时间: 5年前

内容简介:详情参考:
五个UICollectionView常用的知识点

场景2、调用 scrollToRow 停止

五个UICollectionView常用的知识点

场景3、调用 setContentOffset 停止

self.tableView.setContentOffset(CGPoint.init(x: 0, y: 0), animated: false)
print("执行这行代码的时候,已经滚动完毕")
复制代码

二、监听reloadData刷新列表完毕的时机

详情参考: 监听reloadData刷新列表完毕的时机

  • 方法1、通过 layoutIfNeeded 方法,强制重绘并等待完成。
  • 方法2、 reloadData 方法会在主线程执行,通过 GCD ,使后续操作排队在 reloadData 后面执行。一次 runloop 有两个机会执行 GCD dispatch main queue 中的任务,分别在休眠前和被唤醒后。设置 listViewlayoutIfNeeded 为YES,在即将进入休眠时执行异步任务,重绘一次界面。
  • 方法3、自定义 UICollectionViewUITableViewlayoutSubviews 之后当作 reloadData 完成(复杂,但可以更好的理解方法一)

三、自由拖拽

五个UICollectionView常用的知识点

一、iOS9之前思路:

  • 第一步 :给 UICollectionviewCell 添加一个长按手势 UILongPressGestureRecognizer ,通过代理传递到 UIViewController 中。
  • 第二步 :开始长按时( UIGestureRecognizerStateBegan )对 cell 进行截图并且隐藏 cell
  • 第三步 :移动时( UIGestureRecognizerStateChanged )移动截图,遍历得到截图移动到哪个 cell 的位置。调用方法 moveItemAtIndexPath:toIndexPath: 调换两个 cell 的位置,并且更新数据源的顺序。
  • 第四步 :停止时( UIGestureRecognizerStateEnded )移除截图,显示 cell

参考博客:

[iOSUI 进阶拖] 拽 排序 的实现

DraggingSort

LXReorderableCollectionViewFlowLayout

XWDragCellCollectionView

CollectionViewCellDragExchange

二、iOS9之后思路:

  • 第一步:给 UICollectionviewCell 添加一个长按手势 UILongPressGestureRecognizer ,通过代理传递到 UIViewController 中。
  • 第二步:开始长按时( UIGestureRecognizerStateBegan )对cell进行截图并且隐藏 cell 。调用 beginInteractiveMovementForItem
  • 第三步:移动时( UIGestureRecognizerStateChanged )移动截图。调用 updateInteractiveMovementTargetPosition
  • 第四步:停止时( UIGestureRecognizerStateEnded )移除截图,显示 cell 。调用 endInteractiveMovement
// Support for reordering
@available(iOS 9.0, *)
open func beginInteractiveMovementForItem(at indexPath: IndexPath) -> Bool // returns NO if reordering was prevented from beginning - otherwise YES

@available(iOS 9.0, *)
open func updateInteractiveMovementTargetPosition(_ targetPosition: CGPoint)

@available(iOS 9.0, *)
open func endInteractiveMovement()

@available(iOS 9.0, *)
open func cancelInteractiveMovement()
复制代码

参考博客:

iOS UICollectionView高级用法(长按自由移动cell)-新

四、瀑布流

五个UICollectionView常用的知识点

实现瀑布流的基本原理: 找到最短的列,然后把item放到最短的列下面

如下图所示,由于第三列最短,所以第八个Item添加到第三列下面。

五个UICollectionView常用的知识点

既然要找到 最短的列 ,则就需要用一个数据来保存每一列的Y值,推荐 数组 (相对来说性能比 字典 好)。 XRWaterfallLayout 使用 字典 来存储,相比较 数组 的下标直接获取列的高度, 字典 多做了部分 哈希操作 。做瀑布流,图片的尺寸就可能是不固定的,图片的尺寸可以服务器提前返回,然后 cell 直接设置大小。

主要需要重写三个系统方法:详情参考实现: XRWaterfallLayout 1、 - (void)prepareLayout 2、 - (CGSize)collectionViewContentSize 3、 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect

五、浮动的Header

五个UICollectionView常用的知识点

一、在 iOS9

UICollectionView 的头部视图也能像 tableViewheader 一样出现悬浮挂住的效果。

UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init]; 
//header 
flowLayout.sectionHeadersPinToVisibleBounds = YES; 
//footer
flowLayout.sectionFootersPinToVisibleBounds = YES;
复制代码

二、在 iOS9.0

需要自定义 UICollectionViewFlowLayout

#import <UIKit/UIKit.h>
@protocol LZSFloatHeaderFlowLayoutDelegate <NSObject>
-(void)sectionDidFloat:(NSInteger)section;
@end

@interface LZSFloatHeaderFlowLayout : UICollectionViewFlowLayout
@property (nonatomic, weak) id<LZSFloatHeaderFlowLayoutDelegate> mDelegate;
@end
复制代码
#import "LZSFloatHeaderFlowLayout.h"

@interface LZSFloatHeaderFlowLayout()
@property (nonatomic, strong) NSMutableDictionary<NSNumber*, NSNumber*>* mSectionOffsetYDic;
@end

@implementation LZSFloatHeaderFlowLayout
-(NSMutableDictionary<NSNumber *,NSNumber *> *)mSectionOffsetYDic {
    if ( !_mSectionOffsetYDic ) {
        _mSectionOffsetYDic = [NSMutableDictionary dictionary];
    }
    return _mSectionOffsetYDic;
}
- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {
    NSMutableArray *answer = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
    NSMutableIndexSet *missingSections = [NSMutableIndexSet indexSet];
    for (NSUInteger idx=0; idx<[answer count]; idx++) {
        UICollectionViewLayoutAttributes *layoutAttributes = answer[idx];
        if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) {
            [missingSections addIndex:layoutAttributes.indexPath.section];  // remember that we need to layout header for this section
        }
        if ([layoutAttributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) {
            [answer removeObjectAtIndex:idx];  // remove layout of header done by our super, we will do it right later
            idx--;
        }
    }
    // layout all headers needed for the rect using self code
    [missingSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:idx];
        UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader
                                                                                                  atIndexPath:indexPath];
        [answer addObject:layoutAttributes];
    }];
    return answer;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind
                                                                     atIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewLayoutAttributes *attributes = [super layoutAttributesForSupplementaryViewOfKind:kind
                                                                                         atIndexPath:indexPath];
    if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
        UICollectionView * const cv = self.collectionView;
        CGPoint const contentOffset = cv.contentOffset;
        CGPoint nextHeaderOrigin = CGPointMake(INFINITY, INFINITY);
        
        if (indexPath.section+1 < [cv numberOfSections]) {
            NSIndexPath* tIndexPath = [NSIndexPath indexPathForItem:0 inSection:indexPath.section+1]
            UICollectionViewLayoutAttributes *nextHeaderAttributes = [super layoutAttributesForSupplementaryViewOfKind:kind
                                                                                                           atIndexPath:tIndexPath];
            nextHeaderOrigin = nextHeaderAttributes.frame.origin;
        }
        CGRect frame = attributes.frame;
        if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
            frame.origin.y = MIN(MAX(contentOffset.y, frame.origin.y), nextHeaderOrigin.y - CGRectGetHeight(frame));
        }
        else { // UICollectionViewScrollDirectionHorizontal
            frame.origin.x = MIN(MAX(contentOffset.x, frame.origin.x), nextHeaderOrigin.x - CGRectGetWidth(frame));
        }
        attributes.zIndex = 1024;
        attributes.frame = frame;
        if ( self.mSectionOffsetYDic[@(indexPath.section)] && (self.mSectionOffsetYDic[@(indexPath.section)].integerValue != frame.origin.y) ) {
            if ( [self.mDelegate respondsToSelector:@selector(sectionDidFloat:)] ) {
                [self.mDelegate sectionDidFloat:indexPath.section];
            }
        }
        self.mSectionOffsetYDic[@(indexPath.section)] = @(frame.origin.y);
    }
    return attributes;
}
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString *)kind
                                                                                        atIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:kind
                                                                                        atIndexPath:indexPath];
    return attributes;
}
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString *)kind
                                                                                         atIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:kind
                                                                                        atIndexPath:indexPath];
    return attributes;
}
- (BOOL) shouldInvalidateLayoutForBoundsChange:(CGRect)newBound {
    return YES;
}
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

20个月赚130亿

20个月赚130亿

陈士骏、张黎明 / 中国华侨出版社 / 2011-11-17 / 35.00元

YouTube联合创始人陈士骏在书中以朴实亲切的口吻讲述了他的人生经历,以及对学业、事业、梦想、财富、生死等的种种感悟。 童年随全家去美国小镇定居,少年时代迷上计算机编程; 离大学毕业还有几个月时放弃学位,怀揣200美元奔赴硅谷,加入创业公司PayPal,公司上市后成为百万富翁; 因为无法接受PayPal被EbayeBay收购后工程师丧失发言权,和好友一起开创视频网站YouTub......一起来看看 《20个月赚130亿》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码