我一直在思考一种算法,它可以让您知道用户何时滚动过节标题以更新标题,并且经过一些实验,我已经弄清楚如何实现所需的行为。
本质上,每次滚动位置发生变化时,您都需要知道用户在哪个部分并更新标题。您可以通过- 记住集合视图是滚动视图来执行此scrollViewDidScroll
操作。UIScrollViewDelegate
遍历所有标题并找到最接近当前滚动位置的标题,而没有负偏移量。为此,我使用了一个属性来存储每个节标题位置的数组。创建标头时,我将其位置存储在数组中适当的索引处。找到最接近滚动位置(或所述标题的索引位置)的标题后,只需使用适当的标题更新导航栏中的标题。
在中,为您拥有的每个部分viewDidLoad
填充数组属性:NSNull
self.sectionHeaderPositions = [[NSMutableArray alloc] init];
for (int x = 0; x < self.sectionTitles.count; x++) {
[self.sectionHeaderPositions addObject:[NSNull null]];
}
在collectionView:viewForSupplementaryElementOfKind:atIndexPath:
中,使用创建的标题视图的位置更新数组:
NSNumber *position = [NSNumber numberWithFloat:headerView.frame.origin.y + headerView.frame.size.height];
[self.sectionHeaderPositions replaceObjectAtIndex:indexPath.section withObject:position];
在scrollViewDidScroll:
中,执行计算以确定哪个标题适合显示该滚动位置:
CGFloat currentScrollPosition = self.collectionView.contentOffset.y + self.collectionView.contentInset.top;
CGFloat smallestPositiveHeaderDifference = CGFLOAT_MAX;
int indexOfClosestHeader = NSNotFound;
//find the closest header to current scroll position (excluding headers that haven't been reached yet)
int index = 0;
for (NSNumber *position in self.sectionHeaderPositions) {
if (![position isEqual:[NSNull null]]) {
CGFloat floatPosition = position.floatValue;
CGFloat differenceBetweenScrollPositionAndHeaderPosition = currentScrollPosition - floatPosition;
if (differenceBetweenScrollPositionAndHeaderPosition >= 0 && differenceBetweenScrollPositionAndHeaderPosition <= smallestPositiveHeaderDifference) {
smallestPositiveHeaderDifference = differenceBetweenScrollPositionAndHeaderPosition;
indexOfClosestHeader = index;
}
}
index++;
}
if (indexOfClosestHeader != NSNotFound) {
self.currentTitle.text = self.sectionTitles[indexOfClosestHeader];
} else {
self.currentTitle.text = self.sectionTitles[0];
}
一旦用户滚动到某个部分的标题,这将正确更新导航栏中的标题。如果他们向上滚动,它也会正确更新。当他们没有滚动到第一部分时,它也会正确设置标题。然而,它不能很好地处理旋转。如果您有动态内容,它也不会很好地工作,这可能会导致标题视图的存储位置不正确。如果您支持跳转到特定部分,则用户会跳转到上一个部分的部分标题尚未创建的部分,并且该部分不够高,以至于部分标题位于导航栏下方(最后一个部分也许),不正确的标题将显示在导航栏中。
如果有人可以对此进行改进以使其更有效或更好,请这样做,我会相应地更新答案。