内容简介:详情参考:
场景2、调用 scrollToRow
停止
场景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
中的任务,分别在休眠前和被唤醒后。设置listView
的layoutIfNeeded
为YES,在即将进入休眠时执行异步任务,重绘一次界面。 - 方法3、自定义
UICollectionView
、UITableView
,layoutSubviews
之后当作reloadData
完成(复杂,但可以更好的理解方法一)
三、自由拖拽
一、iOS9之前思路:
- 第一步 :给
UICollectionviewCell
添加一个长按手势UILongPressGestureRecognizer
,通过代理传递到UIViewController
中。 - 第二步 :开始长按时(
UIGestureRecognizerStateBegan
)对cell
进行截图并且隐藏cell
。 - 第三步 :移动时(
UIGestureRecognizerStateChanged
)移动截图,遍历得到截图移动到哪个cell
的位置。调用方法moveItemAtIndexPath:toIndexPath:
调换两个cell
的位置,并且更新数据源的顺序。 - 第四步 :停止时(
UIGestureRecognizerStateEnded
)移除截图,显示cell
。
参考博客:
[iOSUI 进阶拖] 拽 排序 的实现
LXReorderableCollectionViewFlowLayout
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)-新
四、瀑布流
实现瀑布流的基本原理: 找到最短的列,然后把item放到最短的列下面
如下图所示,由于第三列最短,所以第八个Item添加到第三列下面。
既然要找到 最短的列 ,则就需要用一个数据来保存每一列的Y值,推荐 数组 (相对来说性能比 字典 好)。 XRWaterfallLayout 使用 字典 来存储,相比较 数组 的下标直接获取列的高度, 字典 多做了部分 哈希操作
。做瀑布流,图片的尺寸就可能是不固定的,图片的尺寸可以服务器提前返回,然后 cell
直接设置大小。
主要需要重写三个系统方法:详情参考实现: XRWaterfallLayout 1、 - (void)prepareLayout
2、 - (CGSize)collectionViewContentSize
3、 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
五、浮动的Header
一、在 iOS9
后
UICollectionView
的头部视图也能像 tableView
的 header
一样出现悬浮挂住的效果。
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; } 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。