当前 tableview 位置的 NSIndexPath

NSIndexPath for current tableview position

我目前正在尝试模拟网站锚标记以快速导航到浏览器页面上的特定点。如果您愿意,我有一个分段控件作为超链接。见下图:

随着我的表格视图部分和行的增长,这将作为用户使用的快速工具派上用场,尤其是对于较小的设备。然而,我 运行 陷入困境,将滚动点与第一个单元格位置等同,但如果可能的话,我宁愿获得部分标题位置。

我的目标是更新 segmentControl.selectedSegmentIndex 点击时(简单部分)以及滚动时(pickle 部分),使其成为更流畅的 UI 交互。

我已经将我的 selectedSegmentIndex 设置为使用这些 NSIndexPathsIBAction:

点击滚动到特定部分
NSIndexPath *aboutIndex = [NSIndexPath indexPathForRow:0 inSection:0];
NSIndexPath *contactIndex = [NSIndexPath indexPathForRow:0 inSection:1];
NSIndexPath *publicationsIndex = [NSIndexPath indexPathForRow:0 inSection:2];
NSIndexPath *settingsIndex = [NSIndexPath indexPathForRow:0 inSection:3];

switch (self.segmentControl.selectedSegmentIndex)
{
    case 0: [self.tableView scrollToRowAtIndexPath:aboutIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];
        break;
    //etc etc
    ...

使用相同的代码,我将它放在 scrollViewDidScroll: 方法中,就像您期望的那样,但我很难获得当前 tableView 滚动点的特定 indexPath。我首先尝试了这个以及 [self.tableView indexPathsForVisibleRows]:

 -(void)scrollViewDidScroll:(UIScrollView *)scrollView {

    NSIndexPath *currentIndex = [self.tableView indexPathForRowAtPoint:CGPointMake(0, self.tableView.contentOffset.y)];
    NSLog(@"current is %@", currentIndex);

    //And then changing the selectedSegmentIndex on scroll:

    if ((currentIndex >= aboutIndex) && (currentIndex < contactIndex)) {
        self.segmentControl.selectedSegmentIndex = 0;
    // other else if's
    ...
}

这有时有效,当它基本上想要时,并且仅当向下滚动时,我在手动向上滚动时得到 null。所以我将其更改为:

if ([currentIndex isEqual:aboutIndex]) {
    self.segmentControl.selectedSegmentIndex = 0;
} else if ([currentIndex isEqual:contactIndex]) {
    self.segmentControl.selectedSegmentIndex = 1;
} else if ([currentIndex isEqual:publicationsIndex]) {
    self.segmentControl.selectedSegmentIndex = 2;
} else if ([currentIndex isEqual:settingsIndex]) {
    self.segmentControl.selectedSegmentIndex = 3;
}

一直有效,向上滚动时除外。为什么我向上滚动时出现空值?

为了回答您的最后一个问题 ("does anyone know how to get a section title's origins?"),UITableView 有一个方法 - (CGRect)rectForSection:(NSInteger)section 将 return 部分的 CGRect。请参阅文档:https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/index.html

由于标题应该在部分的顶部,您应该能够使用矩形的原点作为标题的原点(当然可能必须考虑文本插入)

或者,您也可以使用 - (CGRect)rectForHeaderInSection:(NSInteger)section,因为两者的顶部坐标应该相同。

当然,您可以将它与滚动位置进行比较,以获得那些 CGRect 的相对屏幕位置。

经过大量尝试后,我真的希望它看起来更精致流畅,我找到了一个比 jn_pdx 更好的解决方案。尽管他的回答很足智多谋并且方向正确,但我确实那样尝试过,并为这些部分创建了 CGRects 但我发现滚动到 - (CGRect)rectForSection:(NSInteger)section 的唯一可行方法是 [self.tableView scrollRectToVisible:animated:] ,在执行它时这样矩形就会滚动直到它可见,所以当向下滚动时它会起作用,因为它将 tableView 的最顶部带到它可见的地方,在这种情况下恰好是屏幕的顶部,但是当向上滚动时,它滚动矩形直到它可见,它最终出现在屏幕底部(不理想的效果),因为这是它变得可见的第一个点。因此,我决定保留 NSIndexPath 方法并对其进行引用。我通过实施以下

来完成此操作

点击 segmentedControl:

- (IBAction)segmentIndexChanged:(id)sender {

//Created the NSIndexPaths for all the sections 1st cells
NSIndexPath *aboutIndex = [NSIndexPath indexPathForRow:0 inSection:0];
NSIndexPath *contactIndex = [NSIndexPath indexPathForRow:0 inSection:1];
NSIndexPath *publicationsIndex = [NSIndexPath indexPathForRow:0 inSection:2];
NSIndexPath *settingsIndex = [NSIndexPath indexPathForRow:0 inSection:3];

    //Scroll to the top most part of the cell
    switch (self.segmentControl.selectedSegmentIndex)
    {
    case 0:
        [self.tableView scrollToRowAtIndexPath:aboutIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];
        break;
    case 1:
        [self.tableView scrollToRowAtIndexPath:contactIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];
        break;
    case 2:
        [self.tableView scrollToRowAtIndexPath:publicationsIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];
        break;
    case 3:
        [self.tableView scrollToRowAtIndexPath:settingsIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];
        break;
    default:
        break; 
    } 
}

然后当 UITableView 被手动滚动时,我通过直接关联到它在点击时滚动到的 NSIndexPath 来更新 selectedSegmentIndex

用于滚动UITableView:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView {

//Created a rect correlating to the tapped Index Paths
CGRect aboutRect = [self.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
CGRect contactRect = [self.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]];
CGRect publicationsRect = [self.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:2]];
CGRect settingsRect = [self.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:3]];
//Get the current table view contentOffset point in CGRect form instead of CGFloat
CGRect scrollY = CGRectMake(0, self.tableView.contentOffset.y, self.tableView.bounds.size.width, self.tableView.bounds.size.height);
// NSLog current y point
NSLog(@"scrollY %@", NSStringFromCGRect(scrollY));

//Catch the intersecting points with CGRectContainsRect not CGRectEqualToRect
    if (CGRectContainsRect(scrollY, aboutRect)) {
        self.segmentControl.selectedSegmentIndex = 0;
    } else if (CGRectContainsRect(scrollY, contactRect)) {
        self.segmentControl.selectedSegmentIndex = 1;
    } else if (CGRectContainsRect(scrollY, publicationsRect)) {
        self.segmentControl.selectedSegmentIndex = 2;
    } else if (CGRectContainsRect(scrollY, settingsRect)) {
        self.segmentControl.selectedSegmentIndex = 3;
    }
}

它完美且一致地工作