修改分页retainanceUIScrollView有更强的用户 - Modify UIScrollView to have a stronger paging retainance for the user

- 此内容更新于:2016-01-19
主题:

我需要一个滚动视图与行为比UIKit略有不同。我想获得一个分页滚动视图,但是我想使用一些自定义值的用户必须做触发分页滚动。看起来像系统UIScrollView触发页面变化当用户超过50%的当前页面的滚动。我想让它“困难”为用户切换页面。另外系统UIScrollView考虑动作的速度,所以如果用户滚动很少像素但很快姿态,页面得到交换,我想避免的。

原文:

I need to have a scrollview with a slightly different behaviour than the UIKit one.

What I'd like to obtain is a paged scrollview, but I'd like to use some custom values for the amount of scroll the user must do to trigger the paging.

Looks like the system UIScrollView trigger the page change when the user scrolls for more than 50% of the current page. I'd like to make it "harder" for the user to switch page.

Additionally the system UIScrollView takes into account the velocity of the gesture, so if the user scroll very few pixels but with a quite fast gesture, the page get switched, which I'd like to avoid.

网友:你想实现这个吗?我相信它可以使用未分页表视图,并查看内容在scrollViewDidScroll抵消。

(原文:Have you tried to implement this? I'm sure it could be done using a non-paged table view, and looking at the content offset in scrollViewDidScroll.)

楼主:只是在问,但是为什么TableView吗?我可以使用相同的方法与未分页滚动视图通过观察同一委托方法?

(原文:Just asking, but why a TableView? Could I use the same approach with a non-paged scrollview by watching at the same delegate method?)

网友:对不起,这是一个错误。我的意思是说滚动视图。实际上,你可能想看看抵消scrollViewDidEndDragging:willDecelerate:,并决定是否继续下一页回去。

(原文:Sorry, that was a typo. I meant scroll view. And, actually, you probably want to look at the offset in scrollViewDidEndDragging:willDecelerate:, and decide there whether to go on to the next page or go back.)

楼主:这工作,我将答案中的代码。谢谢你的提示。

(原文:It worked, I will post the code in the answer. Thanks for the tip.)

解决方案:
好吧,我这样来实现的,它工作得非常好:
原文:

Ok, I implemented it this way and it works quite well:

//this is the percentage of page I need to drag to trigger the paging
#define PAGING_THREESHOLD 0.6

//this enum is to keep track of the scrolling direction
typedef enum ScrollDirection {
    ScrollDirectionNone,
    ScrollDirectionRight,
    ScrollDirectionLeft,
    ScrollDirectionUp,
    ScrollDirectionDown,
    ScrollDirectionCrazy,
} ScrollDirection;

//this is to avoid the intertial scrolling
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
                 withVelocity:(CGPoint)velocity
          targetContentOffset:(inout CGPoint *)targetContentOffset {
    *targetContentOffset = scrollView.contentOffset;
}

//here is the custom paging code
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{

    CGPoint destinationOffset = scrollView.contentOffset;
    CGFloat y = (int)destinationOffset.y % (int)scrollView.height;

    if (_scrollDirection == ScrollDirectionDown){
        CGFloat delta = scrollView.height - (scrollView.height - y);
        delta = delta / scrollView.height;
        NSUInteger currentPage = scrollView.contentOffset.y / scrollView.size.height;
        if (delta > PAGING_THREESHOLD && currentPage != scrollView.verticalPageCount - 1){
            //go to next page
            destinationOffset = CGPointMake(destinationOffset.x, (currentPage + 1) * scrollView.height);
        }else{
            destinationOffset = CGPointMake(destinationOffset.x, currentPage * scrollView.height);
        }
    }else if (_scrollDirection == ScrollDirectionUp){
        CGFloat delta = scrollView.height - y;
        delta = delta / scrollView.height;
        NSUInteger currentPage = scrollView.contentOffset.y / scrollView.size.height;
        if (delta > PAGING_THREESHOLD){
            //go to next page
            destinationOffset = CGPointMake(destinationOffset.x, currentPage * scrollView.height);
        }else{
            destinationOffset = CGPointMake(destinationOffset.x, (currentPage + 1) * scrollView.height);
        }
    }
    if (!CGPointEqualToPoint(destinationOffset, scrollView.contentOffset)){
        [scrollView setContentOffset:destinationOffset animated:YES];
    }
}

//here the scrolldirection is calculated
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (self.lastContentOffset.x > scrollView.contentOffset.x){
        _scrollDirection = ScrollDirectionRight;
    } else if (self.lastContentOffset.x < scrollView.contentOffset.x){
        _scrollDirection = ScrollDirectionLeft;
    } else if (self.lastContentOffset.y > scrollView.contentOffset.y){
        _scrollDirection = ScrollDirectionUp;
    } else if (self.lastContentOffset.y < scrollView.contentOffset.y){
        _scrollDirection = ScrollDirectionDown;
    } else{
        _scrollDirection = ScrollDirectionNone;
    }
    self.lastContentOffset = scrollView.contentOffset;
}