Shrinking a UIScrollView to focus on a certain pag

2019-09-16 10:54发布

问题:

I have a UIScrollView with horizontal pagination - similar to the weather app. Under certain circumstances, I want to prevent the user from scrolling horizontally. Simply disabling the scrolling is a little jarring - I would prefer to duplicate the experience of scrolling past the last page - a little scrolling is permitted, but since there is no more content, the scrollview bounces back.

How might I go about implementing this? Should I be changing the contentSize of the ScrollView? How do I set up the pagination so that there is effectively one 'page' but there is still content displayed to the immediate left and right?

回答1:

In order to always make the UIScrollView bounce, even with just one page, add the following line:

[self.scrollView setAlwaysBounceHorizontal:YES];

In addition to my comment about shrinking the contentSize, of course.


EDIT:

OK, let me first explain want we want to achieve. The User is scrolling happily between the pages in the UIScrollView, and suddenly, we want the UIScrollView to stick to the current page, which may or may not be the first page.

Our UIScrollView has the pages laid out, with each page represented by a single UIView or it's subclasses (it may have subviews itself):

Now, to perform the task explained, here is the code:

CGFloat pageWidth = _scrollView.bounds.size.width;
int currentPage = (_scrollView.contentOffset.x / pageWidth);

[_scrollView setContentSize:CGSizeMake(pageWidth, _scrollView.contentSize.height)];
// move each page to the left:
for (UIView* page in _scrollView.subviews) {
    [page setFrame:CGRectOffset(page.frame, -currentPage * pageWidth, 0)];
}

NOTE: If you have a complicated view hierarchy, just wrap it in a UIView that has a bounds size equal to the _scrollView.contentSize with all the pages. The rest I leave it as an exercise for the reader (I always wanted to say that xD)



回答2:

Mazyod's answer above is probably the best one, but I had a lot of trouble returning the views to their original location and resizing the contentSize in a way that is hidden from the user. I used the following approach instead.

I simply create a new scrollview, with a limited size, and lay it over the top of my existing one. I move the three views (the one being used and those either side) into this temporary scrollview, adjusting their origin as per Mazyod's answer.

When I need to revert, I simply move the views back into the real scrollview and remove the temporary one.

Not as efficient, but a viable alternative.