UIScrollView child jumping after UINavigationController push and pop
Asked Answered
N

3

5

So I have a UIScrollView on my iPad app with a single child view (which itself is parent to all the controls). The scrolling all works fine on it. Rotating works fine (the whole view fits in portrait, scrolls on landscape). Once pushing a new screen on the UINavigationController, and then coming back breaks it.

It looks as if the frame of the scrollview's child has moved up, relative to the scroll position, but the scrollview has remained at the bottom (the entire child view has shifted upwards).

I've tried fighting the Constraints in storyboard, literally for hours, and cannot work out what could be causing this.

How it starts How it looks like after navigating and returning

Nesline answered 16/11, 2012 at 17:0 Comment(4)
Tried the constraints options?Amii
yes, as said in the questionNesline
Did you ever figure anything out? I've seen the same behavior on an iPhone where there is a scroll view inside a navigation controller. One other thing I noticed is that if I push and pop again it is set correctly. So every other time it seems to have a problem.Colorimeter
No, I didn't ever figure it out. If you do yourself, do update.Nesline
G
1

I had the same problem with scroll view and auto layouts (iOS 6 - doesn't work, iOS 7 - works fine), of course this is not perfect solution, but seems like it works. Hope it will help you:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self performSelector:@selector(content) withObject:nil afterDelay:0.0];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    offset = self.scrollView.contentOffset;
}

- (void)viewDidDisappear:(BOOL)animated
{
   [super viewDidDisappear:animated];

   self.scrollView.contentOffset = CGPointZero;
}

- (void)content
{
    [self.scrollView setContentOffset:offset animated:NO];
}
Gunderson answered 27/3, 2014 at 21:39 Comment(0)
S
0

Get the frame of the subview before it disappears then manually reset the frame of the subview every time the view appears in -(void)viewWillAppear:(BOOL)animated.

-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
globalFrameVariable = subview.frame;
[subview removeFromSuperview];
}

-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[subview setFrame:globalFrameVariable];
[scrollView addSubview:subview];
}
Shaquana answered 26/7, 2013 at 6:42 Comment(0)
R
0

Here is a simple solution i found. (Assuming the parent view is meant to span the entire contentSize) Use this subclass of UIScrollView:

@interface BugFixScrollView : UIScrollView
@end
@implementation BugFixScrollView
-(void)layoutSubviews
{
    [super layoutSubviews];
    UIView *view=[self.subviews firstObject];
    if(view)
    {
        CGRect rect=view.frame;
        rect.origin=CGPointMake(0, 0);
        view.frame=rect;
    }
}
@end

It simply resets the origin every time auto-layout messes it up. this class can be used in InterfaceBuilder simply by changing the class name after placing the UIScrollView.

River answered 10/6, 2015 at 3:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.