Mathias Aichinger
Mathias Aichinger

Reputation: 893

UIScrollview Autolayout Issue

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?

Upvotes: 31

Views: 18872

Answers (9)

Jimvanced
Jimvanced

Reputation: 1

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;
}

Upvotes: 0

Lukas
Lukas

Reputation: 2535

have you tried this?

self.automaticallyAdjustsScrollViewInsets = NO;

In my case this was what solved my problem.

Upvotes: 1

Ratha Hin
Ratha Hin

Reputation: 680

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;
}

Upvotes: 1

Holger Schmeken
Holger Schmeken

Reputation: 651

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];
}

Upvotes: 1

mimc
mimc

Reputation: 111

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.

Upvotes: 0

Kukosk
Kukosk

Reputation: 3012

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;
    }
}

Upvotes: 6

Adam Waite
Adam Waite

Reputation: 18845

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.

Upvotes: 3

user1071136
user1071136

Reputation: 15725

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.

Upvotes: 40

kadore
kadore

Reputation: 131

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 ;)

Upvotes: 11

Related Questions