UIScrollview Autolayout Issue
Asked Answered
J

9

31

I have a problem with autolayout(maybe) and my scrollview!

My Problem

  1. I scroll down View

2.Then I push to another View

3.Then I go back and the scrollview looks like that and I'm not able to scroll to the highest point.(I see it in the bouncing of the scrollview) Scrollview

Can anybody help me?

Juncture answered 25/9, 2012 at 9:50 Comment(5)
did you set the frame size correctly ?Vaquero
if you are coding scrollview programmatically without nib, add the code chunk to the question .. this can help you get better answersVaquero
I'm coding nothing! everything was set in the interfacebuilderJuncture
set frame of scroll view like this CGRect scrollFrame = CGRrectMake(x, y, width , height ); ScrollView.frame = scrollFrame;Vaquero
Fixed this issue at the related thread https://mcmap.net/q/261415/-uiscrollview-wrong-offset-with-auto-layoutPyro
Z
40

The following code snippet in the containing view controller also seems to solve the problem, without relying on explicit sizes:

- (void)viewDidDisappear:(BOOL)animated {
  [super viewDidDisappear:animated];
  self.mainScrollView.contentOffset = CGPointZero;
}

It does reset the content offset to the origin, but it seems that so do the other answers.

Zelmazelten answered 10/11, 2012 at 21:36 Comment(8)
this works! but when i set it back to the right value(in viewdidappear) it is flickering! so I continue looking for a better way....Juncture
set right offset in viewDidLayoutSubviews back and everything is fine :)Juncture
This is an unbelievably and frustrating bug/issue. People aren't prepared to deal with this bug when setting things up in Interface Builder.Chaeta
I had to use this fix also, but before I presented my UIViewController I let the scrollView scroll to the top. My scrollView was off-screen so I had no flickering. But you could create a method to reset the scrollview to its origin point and call it after 1 second or so (performSelector:withObject:afterDelay:); when you start presenting your UIViewController.Froh
Looks like that Apple has fixed this issue in the newest iOS! :)Juncture
@matchi1992 I have the most recent version, and I'm facing this issue. Can someone tell why this happen? please.Halfandhalf
@Halfandhalf do you found the workaround? I have Xcode 6.2Angelenaangeleno
@Angelenaangeleno Bens, not exactly a workaround. I redesigned the the interface with new/different auto-layout constraints. First I had lots of uibuttons inside a single view, and I was trying to place the view in the scrollView. I took out the view, so i placed all buttons and views directly on scrollView, I fixed one relative to scrollView, and the others relative to the first.. And it worked.Halfandhalf
F
11

if you are still searching for an answer i found it today after two days of headbanging the wall. I will just paste you the code, but the most important thing is when you load your scrollView..

    -(void)viewWillAppear:(BOOL)animated{

    [scrollView setFrame:CGRectMake(0, 0, 320, 800)];
}

-(void)viewDidAppear:(BOOL)animated
{
    [scrollView setScrollEnabled:YES];
    [scrollView setContentSize:CGSizeMake(320, 800)];

}

all this is loaded before -(void)viewDidLoad

notice the height is in both instances 800, which is crucial for resolving this problem. good luck with your project ;)

Fuji answered 2/11, 2012 at 14:10 Comment(0)
H
6

I was using adam's solution, but started to have problems when i was dismissing with animated:YES. In my code, content offset gets set a while after viewWillAppear (as viewWillAppear appears to be too soon).

- (void)viewDidDisappear:(BOOL)animated
{
    self.scrollOffsetToPersist = self.scrollView.contentOffset;
    self.scrollView.contentOffset = CGPointZero;

    [super viewDidDisappear:animated];
}

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

    [[NSOperationQueue mainQueue] addOperationWithBlock:^
     {
         self.scrollView.contentOffset = self.scrollOffsetToPersist;
     }];
}

EDIT: another, better way is to reset it back in viewDidLayoutSubviews :)

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    if(!CGPointEqualToPoint(CGPointZero, self.scrollOffsetToPersist))
    {
        self.scrollView.contentOffset = self.scrollOffsetToPersist;
        self.scrollOffsetToPersist = CGPointZero;
    }
}
Hallowell answered 29/1, 2013 at 18:45 Comment(2)
Note that if you set it in viewDidLayoutSubviews, you may need to also save the offset in viewDidDisappear: or scrollview offset will jump to zero when you present a modal view controller and won't reset properly. I filed a bug with Apple on this behavior as well: openradar.appspot.com/radar?id=3011407Nonrestrictive
I solve my problem using NSoperationQueue putting in the viewDidLayoutSubviews method and set contectsize of scrollview.Thanks @kukoskTube
T
3

This isn't great but I beat auto-layout (definitely not the correct way but I was sick of trying!) by setting the content size in viewDidAppear after autolayout happens, setting the scrollOffset and persisting the scroll offset in viewDidDisappear, and then setting the scroll offset back to it's persisted state in viewDidAppear.

Like this:

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:YES];
    self.scrollView.contentSize = self.scrollViewInnerView.frame.size;
    self.scrollView.contentOffset = [self.scrollOffsetToPersist CGPointValue];

}

-(void)viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:YES];
    self.scrollOffsetToPersist = [NSValue valueWithCGPoint:self.scrollView.contentOffset];
    self.scrollView.contentOffset = CGPointZero;
}

Not at all elegant, but works so thought I'd share.

Tiv answered 7/12, 2012 at 7:39 Comment(2)
apple wrote the same thing... probably the best solution so far... but I think viewDidLayoutSubviews is the better position to set the offset backJuncture
Yep this is what worked for me. A simple idea such as resizing subviews in a scroll view, the execution is rather complex... Spent hours messing around with UIScrollView and autolayout before finally settling on this.Emersion
A
1

I use an UITabBarController and different views with auto layout. The views are longer than the screen of the device. Switching from one tab to the other lead sometimes to the problem you describe. This only happened if the view has been scrolled down before the switch. I tried all the advice here but this did not work for my case. My solution was to scroll up again before leaving the view. At least a work around for this bug in iOS 6:

-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [scrollView setContentOffset:CGPointZero animated:NO];
}
Argueta answered 5/8, 2013 at 22:45 Comment(0)
A
1

The issue cause ScrollView was set ContentOffset before AutoLayout applied. the solution is:

Create private property

@property (assign,nonatomic) CGPoint scrollviewContentOffsetChange;

Add code to view method

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  self.scrollView.contentOffset = CGPointZero;
}

- (void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];
  self.scrollviewContentOffsetChange = self.scrollView.contentOffset;
}

- (void)viewDidLayoutSubviews {
  [super viewDidLayoutSubviews];

  self.scrollView.contentOffset = self.scrollviewContentOffsetChange;
}
Allhallows answered 29/8, 2013 at 10:16 Comment(0)
I
1

have you tried this?

self.automaticallyAdjustsScrollViewInsets = NO;

In my case this was what solved my problem.

Isopod answered 4/4, 2014 at 12:5 Comment(2)
this was an iOS 6 issue. in iOS 7 everything is fine!Juncture
this problem come back in ios9Othilie
C
0

I had the same problem. Turned out I was setting a constraint on the content view aligning the it's y-center to the superview's y-center. When I deleted this constraint it worked just fine.

Congreve answered 19/2, 2013 at 22:6 Comment(0)
U
0

try this

@property (nonatomic, assign) CGPoint scrollViewContentOffsetChange;

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.scrollView.contentOffset = CGPointZero;
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    self.scrollViewContentOffsetChange = _scrollView.contentOffset;
}

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    _scrollView.contentOffset = self.scrollViewContentOffsetChange;
}
Uredium answered 28/7, 2014 at 9:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.