3

I have a UIScrollView with paging enabled but I would like to be able to prevent the user to swipe to the next page or back to the previous page in some cases.

For instance someone could be passing a test with ten questions (one question per page) but scrolling won't work unless the person has answered the question at the current page.

It could also be to prevent them to swipe back to the previous page. So basically I cannot use directional lock or temporarily disable user interaction because the reader could be allowed to swipe left but not to swipe right.

I noticed a few people play around with the content offset but I find that solution ugly because the user can still swipe, it's just that the app automatically readjusts the content offset. I would like it to be as if the view had reached the end of the content or if user interaction was disabled.

I guess I could maybe "play" with the content size/offset and refresh it on each page but I am not sure how to do that properly as I also have "links" that can allow someone to jump from one page to another (that could at the time be outside the defined content).

I have tried using a custom view for pages where swipe in a specific direction is locked but it doesn't work as I could not find a way to prevent the scroll view from detecting the swipe without affecting pages were swipe should work in a normal way. I saw that I could set that custom view exclusiveTouch property to YES and assumed that since it was going to get all the events I could handle swipes via custom gesture recognizers and forward the events if swipe was allowed or ignore them if not. It did not work, the ScrollView always catches swipe events.

I feel I have exhausted every possibility and I cannot find anyone who had similar needs.

So I am wondering, is this even possible? If yes, will it require bad hacks or to make a new custom scroll view?

Any help/idea would be greatly appreciated.

Deratrius
  • 679
  • 10
  • 21

2 Answers2

1

use your condition at the appropriate place in your code where you want the scroll/paging locked and set pagingEnabled or scrollEnabled of your scrollView object to NO.

EDIT:

Should've read your requirement more carefully. For your needs a better solution would be to use multiple views slide in and out from the sides based on your conditionals. Animate them. Gesture recognizers should also help. And I'm not talking scrollView here. View1 -> condition -> passes? (button action or gesture) -> animation into view2 and so on.

If you really must use the scrollView, the best you can do is to set the contentSize to the width of the screen and set alwaysBounceHorizontal to NO to prevent the automatic bouncing effect:

CGRect size = scrollView.contentSize;
size.width = CGRectGetWidth(scrollView.frame);
scrollView.contentSize = size;
scrollView.alwaysBounceHorizontal = NO;
Bourne
  • 10,094
  • 5
  • 24
  • 51
  • This will not work, as I said, I need to be able to scroll Left but not Right (or right but not left). This solution will block swipes in both directions. – Deratrius Sep 29 '11 at 07:40
  • Yes, I think setting the contentSize "manually" and bounce to NO with a view on top that catches swipes through UIGesture recognizers and filters them is the only way to go. Alas, it seems that the scroll view always catches the swipes unless userInteraction is disabled. Which means I would need to use that custom swipe filter detecting view everywhere (even when it's not necessary). I may end up having to do it but was hoping that maybe there was an easier solution. Thanks for the help though! – Deratrius Oct 03 '11 at 07:54
0

Found in another post, this is how I solved the same problem I had.

Put this in you view controller and set it as the delegate of the UIScrollView

CGPoint oldOffset;  // instance variable

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    oldOffset = scrollView.contentOffset;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (scrollView.contentOffset.x < oldOffset.x) 
    {
        [scrollView setContentOffset:oldOffset];
    }
}
Murat Ögat
  • 1,342
  • 2
  • 14
  • 24
  • I have been off that project for like a year and half so I can't really test this solution. Thanks for posting it though! Maybe it will help other people with the same problem. – Deratrius May 07 '13 at 14:45
  • Yeah I noticed it's an old one but I wanted to post anyway. After implementing it, I got almost the desired behaviour. The only problem I noticed after testing is that sometimes the scroll view can scroll 5-10 px to the right, although I have paging enabled. (Probably due to a strange gesture) So it's not actually a perfect solution, but this small scroll can be handled by checking visible rect and scrolling back if necessary. Let's hope it helps someone. – Murat Ögat May 07 '13 at 21:16