Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reset my UIScrollView's position after returning from a modal transition?

I have a simple view containing a long view with many buttons, with the whole thing being in a UIScrollView. The scroller works well, and I can scroll to the bottom and click a button. Every button triggers a modal seque to another view. That new view is then dismissed by user interaction, causing the original UIScrollView's view to load again.

Here's the problem: If I click on a button toward the top of the UIScrollView, I enter the modal segue, dismiss the new view, and return to the UIScrollView's view without a problem. But, if I click on one of the buttons toward the bottom of the UIScrollView, when I return seque out and then transition back, my scrolling is all messed up. I can only see the area beneath my scroller, and can't scroll back up to the top anymore!

I'm pretty sure there must be some way to reset the UIScrollView's starting and ending points upon ViewWillAppear, but I can't figure it out. Any help is appreciated!

Also, FYI, I simply added the UIScrollView through interface builder, and haven't implemented or synthesized it anywhere yet.

like image 413
jake9115 Avatar asked Jun 06 '13 04:06

jake9115


People also ask

How do I center an image in ScrollView?

We just need to update the offset of the image in the method scrollViewDidZoom (remember to set delegate UIScrollViewDelegate in your code). If the content size of scroll view (which means the size of image view) is smaller than the scroll view, we adjust the center of image view. Or else set it to (0,0).

What is content offset in ScrollView in Swift?

contentOffset is the point at which the origin of the content view is offset from the origin of the scroll view. In other words, it is where the user has currently scrolled within the scroll view. This obviously changes as the user scrolls.


2 Answers

try this code:

- (void)viewWillAppear:(BOOL)animated
{
  [yourscrollview setContentOffset:CGPointZero animated:YES];
}
like image 55
kirti Chavda Avatar answered Oct 17 '22 20:10

kirti Chavda


Please note: the bug this question and answer is about appears to be fixed in iOS 7. The rest of this answer is only relevant to iOS 6 (and probably earlier).

The behaviour being exhibited here is a bug in the UIScrollView class. As noted by the OP, after returning from a modally presented UIViewController to a scene containing a UIScrollView, the UIScrollView takes whatever point it's currently scrolled to and starts behaving as though that is its origin. That means that if you'd scrolled down your scroll view before modally presenting another View Controller, you can't scroll back up upon returning to the scene with the scroll view.

The same thing happens when you remove the Scroll View from the view hierarchy and re-add it, even without changing its window.

You can work around this by setting the contentOffset of the scroll view back to {0,0} before it gets displayed again after dismissing the modal View Controller. If you actually want to preserve the point the user had scrolled to before they triggered the modal, then after the UIScrollView is redisplayed you can set the contentOffset back to whatever it was before you reset it.

Here's a UIScrollView subclass that fixes the bug without resetting the scroll view to the top whenever you return from a modal:

@interface NonBuggedScrollView : UIScrollView

@end

@implementation NonBuggedScrollView {
    CGPoint oldOffset;
}

-(void)willMoveToWindow:(UIWindow *)newWindow {
    oldOffset = self.contentOffset;
    self.contentOffset = CGPointMake(0,0);
}

-(void)willMoveToSuperview:(UIView *)newSuperview {
    oldOffset = self.contentOffset;
    self.contentOffset = CGPointMake(0,0);
}

-(void)didMoveToWindow {
    self.contentOffset = oldOffset;
}

-(void)didMoveToSuperview {
    self.contentOffset = oldOffset;
}

@end

If you'd rather do this in a UIViewController than in a UIScrollView subclass, change the content offset in the viewWillAppear: and viewDidAppear methods.

If you don't want to preserve where the user's scroll position when they return from a modal, and just want to scroll the UIScrollView back to the top, as the OP asked for, then all you need is the even simpler:

@interface NonBuggedScrollView : UIScrollView

@end

@implementation NonBuggedScrollView

-(void)willMoveToWindow:(UIWindow *)newWindow {
    self.contentOffset = CGPointMake(0,0);
}

-(void)willMoveToSuperview:(UIView *)newSuperview {
    self.contentOffset = CGPointMake(0,0);
}


@end
like image 21
Mark Amery Avatar answered Oct 17 '22 19:10

Mark Amery