scrollViewWillEndDragging:withVelocity:targetContentOffset: not working on the edges of a UISCrollView
Asked Answered
B

5

31

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.

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.

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.

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.

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
Bahaism answered 4/6, 2012 at 11:23 Comment(0)
B
16

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.

Bahaism answered 27/6, 2012 at 11:21 Comment(2)
I'm also experiencing this issue. Any chance you could post the Apple bug ID number—or better, a link to the OpenRadar entry—to assist myself, and possibly others, in posting a duplicate bug report? (It's fairly well-known that Apple prioritise fixing bugs based on the number of reports they receive.)Charin
Sure. It's a duplicate of 10255505 but it seems that doesn't exist in OpenRadar. Anyway it seems to be closed now, but I don't know if they'll release the fix or not.Bahaism
M
9

Issue Fixed on iOS 6.0.

Now it works as it should.

Merrygoround answered 10/10, 2012 at 13:8 Comment(0)
J
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:

- (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.

Jamshid answered 18/9, 2012 at 11:13 Comment(0)
F
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.

Fusilier answered 26/6, 2012 at 23:37 Comment(1)
Thank you very much for your answer. You're right. I, too, investigated and talked to other people and found out it was a bug. Just forgot to answer my own question, sorry (if you want more detail please take a look at it). An offset like 0.1 seems to do it. Anyway, thank you very much.Bahaism
L
0

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

[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.

Libradalibrarian answered 9/8, 2012 at 0:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.