scrollviewwillenddrag:withVelocity:targetContentOffset:不处理UISCrollView的边缘

时间:2023-01-23 17:06:32

I'm trying to implement a custom tab bar which is scrollable and has paging at each tab bar item. For that i'm using the delegate scrollViewWillEndDragging:withVelocity:targetContentOffset: which works perfectly with one problem.

我正在尝试实现一个自定义选项卡栏,它是可滚动的,在每个选项卡栏项上都有分页。为此,我使用委托scrollviewwillenddrag:withVelocity:targetContentOffset:它可以很好地处理一个问题。

The way my paging works is, if the contentOffset is near the right item, it the targetContentOffset changes to the offset of that item. Same thing for the left side.

我的分页工作的方式是,如果contentOffset位于正确的项附近,则它的targetContentOffset更改为该项目的偏移量。左边也是一样。

The problem is, whenever I'm at at the left half of the first item and the right of the last (the scroll view works horizontally) it's supposed to go to ContentOffset 0 and the content offset of the rightmost item (minus the ones on screen), but it doesn't.

问题是,当我在第一个条目的左半部分和最后一个条目的右半部分(滚动视图水平工作)时,它应该指向ContentOffset 0,以及最右边条目的内容偏移量(减去屏幕上的内容),但是它没有。

I checked with the debugger and the targetContentOffset->x is indeed 0 (in the first case - left of the leftmost item). So the problem is the UIScrollView not scrolling there. I'm lost.

我用调试器检查了一下,targetContentOffset->x实际上是0(在第一种情况下,最左边的项目左边)。问题是UIScrollView没有滚动。我迷路了。

Here is my implemented delegate:

这是我实现的委托:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
                 withVelocity:(CGPoint)velocity
          targetContentOffset:(inout CGPoint *)targetContentOffset{
     NSInteger index = lrintf(targetContentOffset->x/self.tabWidth);
     targetContentOffset->x = index * self.tabWidth;
}

Here is the diagram explaining what i want to do.

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

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

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

   <----|

   |_______________________________________|
              where it would stop

|_______________________________________|
        where i want it to stop

5 个解决方案

#1


14  

This is a known issue it seems. After some investigation and talking to other people it was suggested it could be a bug, which turned out to be correct. I reported it to Apple and was it marked as duplicate but is still open. Just answering for those of you with the same problem. I workaround it like Big Papoo suggests, by using an offset close to what I want (0.1 seems to do it). The same for the right end.

这似乎是一个众所周知的问题。经过调查和与他人交谈后,有人认为它可能是一个bug,结果证明是正确的。我向苹果报告了它,它被标记为副本,但仍然是开放的。只是回答你们中有同样问题的人。我按照Big Papoo的建议来处理它,使用一个接近我想要的偏移量(0.1似乎可以做到)。对右端也是一样。

#2


9  

Issue Fixed on iOS 6.0.

在ios6.0上修正。

Now it works as it should.

现在它的工作方式是应该的。

#3


8  

I tried setting the final offset to something slightly off zero or the content size as suggested by Big Papoo but noticed that this removes the over-scroll bounce. My solution to this was to check the original targetContentOffset to see if it is equal to zero or the contentSize and leaving it if it is:

我试着将最后的偏移量设置为0或大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;
}

You can of course then use scrollViewDidEndDecelerating: to to move the scrollview that 1 point.

当然,您可以使用scrollviewdidendcooling:将scrollview移动1点。

#4


3  

I found 2 undocumented behaviors that you may investigate : - Setting zero as the final offset doesn't work, I suggest putting 1 or anything greater than zero (0.5 may work, not tested) - You'd better check the velocity sign and compute your final offset to be on the left or right side of the current point where the user removed is finger. Don't try to make the scrolling go backward on the other side.

我发现2非法行为,你可以调查:——设置零作为最终抵消不起作用,我建议把1或任何大于0(0.5可以工作,没有测试)-你最好检查速度信号,计算期末抵消左侧或右侧的当前用户删除的手指。不要试图让滚动条在另一边向后滚动。

#5


0  

If you're using a horizontal table view, then inside your scrollViewWillEndDragging:withVelocity:targetContentOffset: function, you can call:

如果使用的是水平表格视图,那么在scrollviewwillenddrag:withVelocity:targetContentOffset: function,可以调用:

[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:<index> inSection:<section>] atScrollPosition:UITableViewScrollPositionTop animated:YES];

I found this to work much better than trying to manipulate targetContentOffset->y in a horizontal table view.

我发现这比在水平表视图中操作targetContentOffset->y要有效得多。

#1


14  

This is a known issue it seems. After some investigation and talking to other people it was suggested it could be a bug, which turned out to be correct. I reported it to Apple and was it marked as duplicate but is still open. Just answering for those of you with the same problem. I workaround it like Big Papoo suggests, by using an offset close to what I want (0.1 seems to do it). The same for the right end.

这似乎是一个众所周知的问题。经过调查和与他人交谈后,有人认为它可能是一个bug,结果证明是正确的。我向苹果报告了它,它被标记为副本,但仍然是开放的。只是回答你们中有同样问题的人。我按照Big Papoo的建议来处理它,使用一个接近我想要的偏移量(0.1似乎可以做到)。对右端也是一样。

#2


9  

Issue Fixed on iOS 6.0.

在ios6.0上修正。

Now it works as it should.

现在它的工作方式是应该的。

#3


8  

I tried setting the final offset to something slightly off zero or the content size as suggested by Big Papoo but noticed that this removes the over-scroll bounce. My solution to this was to check the original targetContentOffset to see if it is equal to zero or the contentSize and leaving it if it is:

我试着将最后的偏移量设置为0或大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;
}

You can of course then use scrollViewDidEndDecelerating: to to move the scrollview that 1 point.

当然,您可以使用scrollviewdidendcooling:将scrollview移动1点。

#4


3  

I found 2 undocumented behaviors that you may investigate : - Setting zero as the final offset doesn't work, I suggest putting 1 or anything greater than zero (0.5 may work, not tested) - You'd better check the velocity sign and compute your final offset to be on the left or right side of the current point where the user removed is finger. Don't try to make the scrolling go backward on the other side.

我发现2非法行为,你可以调查:——设置零作为最终抵消不起作用,我建议把1或任何大于0(0.5可以工作,没有测试)-你最好检查速度信号,计算期末抵消左侧或右侧的当前用户删除的手指。不要试图让滚动条在另一边向后滚动。

#5


0  

If you're using a horizontal table view, then inside your scrollViewWillEndDragging:withVelocity:targetContentOffset: function, you can call:

如果使用的是水平表格视图,那么在scrollviewwillenddrag:withVelocity:targetContentOffset: function,可以调用:

[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:<index> inSection:<section>] atScrollPosition:UITableViewScrollPositionTop animated:YES];

I found this to work much better than trying to manipulate targetContentOffset->y in a horizontal table view.

我发现这比在水平表视图中操作targetContentOffset->y要有效得多。