如何在不同Segment(标签页)中维持CollectionView的状态
解决分段切换时UICollectionView滚动位置丢失的问题
这个问题在复用单个CollectionView做分段内容展示时很常见——每次切换分段调用reloadData会直接重置滚动状态,咱们通过为每个分段单独保存滚动位置就能解决,具体方案如下:
1. 添加存储滚动位置的属性
首先在你的ViewController类里声明一个字典,用来存储每个分段对应的滚动偏移量:
@property (nonatomic, strong) NSMutableDictionary *segmentScrollPositions;
然后在viewDidLoad里初始化它:
- (void)viewDidLoad { [super viewDidLoad]; self.segmentScrollPositions = [NSMutableDictionary dictionary]; // 其他初始化代码... }
2. 修改分段切换方法,加入保存与恢复逻辑
在切换分段的方法中,先保存当前分段的滚动位置,处理完新分段的数据加载后,再恢复目标分段的历史位置:
-(IBAction)changeSeg:(id)sender{ // 第一步:保存当前选中分段的滚动位置 NSInteger currentSegment = self.segmentedControl.selectedSegmentIndex; CGPoint currentOffset = self.collectionView.contentOffset; [self.segmentScrollPositions setObject:[NSValue valueWithCGPoint:currentOffset] forKey:@(currentSegment)]; // 第二步:处理新分段的数据加载逻辑 [collectionView reloadData]; NSInteger newSegment = self.segmentedControl.selectedSegmentIndex; if(newSegment == 0){ typeFlag = 0; if ([inventoryDetails count] == 0 && totalInventoryCountForAll != 0) { [self loadMore]; } else if (totalInventoryCountForAll == 0) { [self setNoCarVisibility: true]; } } else if(newSegment == 1){ typeFlag = 1; if ([newInventory count] == 0 && totalInventoryCountForNew != 0) { [self loadMore]; } else if (totalInventoryCountForNew == 0) { [self setNoCarVisibility: true]; } } else if(newSegment == 2){ typeFlag = 2; if([usedInventory count] == 0 && totalInventoryCountForUsed != 0){ [self loadMore]; } else if (totalInventoryCountForUsed == 0) { [self setNoCarVisibility: true]; } } // 第三步:恢复新分段的历史滚动位置 NSValue *savedOffsetValue = [self.segmentScrollPositions objectForKey:@(newSegment)]; if (savedOffsetValue) { CGPoint savedOffset = [savedOffsetValue CGPointValue]; // 直接设置偏移量,若loadMore是异步加载,需在数据回调后再执行此步骤 [self.collectionView setContentOffset:savedOffset animated:NO]; } else { // 第一次进入该分段时默认滚到顶部 [self.collectionView setContentOffset:CGPointZero animated:NO]; } }
3. 额外注意事项
- 如果你的
loadMore是异步加载数据,要把恢复滚动位置的代码放到数据加载完成的回调里,确保CollectionView的contentSize已经更新后再设置偏移量。 - 你已经为三个分段维护了独立的数据源数组(
inventoryDetails、newInventory、usedInventory),这一点做得很对,保证了reloadData时能正确展示对应分段的内容。
这样修改后,每次切换分段都会保留之前的滚动位置,再也不会出现切回分段时位置跳变的问题啦!
内容的提问来源于stack exchange,提问作者BharathRao
相关产品推荐
相关产品推荐

