scrollViewWillEndDragging:withVelocity:targetContentOffset: 在UIScrollView边缘无法正常工作

30
我正在尝试实现一个自定义的选项卡,它可以滚动并且每个选项卡都有分页。为此,我使用了代理方法`scrollViewWillEndDragging:withVelocity:targetContentOffset:`,这个方法工作得很好,但还存在一个问题。
我的分页方式是,如果`contentOffset`接近右侧的选项卡,则`targetContentOffset`会更改为该选项卡的偏移量。左侧也是同样的操作。
问题在于,每当我位于第一个选项卡的左半部分和最后一个选项卡的右侧(滚动视图是水平的)时,它应该转到`ContentOffset`为0和最右边的项目内容偏移量(减去屏幕上显示的选项卡),但它没有这样做。
我使用调试器检查了一下,发现`targetContentOffset->x`确实为0(在第一种情况下-最左边的选项卡的左侧)。因此问题在于UIScrollView没有滚动到那里。我迷失了方向。
这是我实现的代理方法:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
                 withVelocity:(CGPoint)velocity
          targetContentOffset:(inout CGPoint *)targetContentOffset{
     NSInteger index = lrintf(targetContentOffset->x/self.tabWidth);
     targetContentOffset->x = index * self.tabWidth;
}

这里是解释我想做什么的图示。

|-------|-------|-------|-------|-------|-------|-------|
|       |       |       |       |       |       |       |
|       |       |       |       |       |       |       |
|_______|_______|_______|_______|_______|_______|_______|

        |_______________________________________|
         where it is and i scroll it to the left

   <----|

   |_______________________________________|
              where it would stop

|_______________________________________|
        where i want it to stop
5个回答

16

这似乎是一个已知的问题。经过一些调查和与其他人的交谈,有人建议可能是一个bug,后来证实确实如此。我向苹果报告了这个问题,并被标记为重复,但仍然未解决。我回答这个问题是为了那些有同样问题的人。我像Big Papoo建议的那样通过使用接近所需位置的偏移量(0.1似乎可以)来解决它。右侧也是同理。


我也遇到了这个问题。您能否发布苹果的错误ID号码,或者更好的是,提供一个OpenRadar条目的链接,以帮助我自己和其他人发布重复的错误报告?(众所周知,苹果根据他们收到的报告数量来优先修复错误。) - Calrion
当然。它是10255505的副本,但似乎在OpenRadar中不存在。不管怎样,它似乎已经关闭了,但我不知道他们是否会发布修复补丁。 - dvieira

9

iOS 6.0的问题已得到解决。

现在它可以正常工作了。


8

我尝试按照Big Papoo的建议将最终偏移量设置为略微偏离零或内容大小,但发现这会消除过度滚动反弹。我的解决方案是检查原始的targetContentOffset是否等于零或内容大小,如果是,则保留它:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {

    float expectedOffset = targetContentOffset->x;
    if (expectedOffset == 0 || expectedOffset == scrollView.contentSize.width) return; // Scroll view will bounce so leave the targetContentOffset.

    float targetOffset = [self roundedOffset:expectedOffset]; // Round your offset.

    // Adjust the offset to make sure it works.
    if (targetOffset == 0) targetOffset = 1;
    else if (targetOffset == SCROLLVIEW_WIDTH) targetOffset = SCROLLVIEW_WIDTH - 1;

    targetContentOffset->x = targetOffset;
}

当然,您可以使用scrollViewDidEndDecelerating:来将滚动视图移动1个点。

3

我发现了两个未记录的行为,您可以进行调查: - 将0设置为最终偏移量无效,建议将其设为1或任何大于零的值(0.5可能有效,但未经测试) - 您最好检查速度符号并计算您的最终偏移量是在用户移除手指的当前点的左侧还是右侧。不要尝试使滚动在另一侧向后移动。


非常感谢您的回答。您是正确的。我也进行了调查并与其他人交谈,发现这是一个错误。只是忘记回答自己的问题,很抱歉(如果您想要更多细节,请看一下)。像0.1这样的偏移量似乎可以解决问题。无论如何,非常感谢。 - dvieira

0
如果您正在使用水平表视图,则在scrollViewWillEndDragging:withVelocity:targetContentOffset:函数内,您可以调用以下函数:
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:<index> inSection:<section>] atScrollPosition:UITableViewScrollPositionTop animated:YES];

我发现这比在水平表视图中尝试操纵targetContentOffset->y要好得多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接