Gulfer
Gulfer

Reputation: 101

Scroll View Content Width Change During Rotation (Autolayout) - Scroll View wrong size

I have a scroll view that has a content view inside of it.

The scroll view has constraints to the top, bottom, leading and trailing content view and top, leading, trialing superview with the bottom space to the bottom layout.

I change the Content View width on rotation:

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation      duration:(NSTimeInterval)duration{
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
    _contentWidth.constant = 480; 
}else{
    //iPhone Portrait
    _contentWidth.constant = 320;
    }
}

When I run the app and rotate to landscape, the width of the Content View changes and everything looks good, but the scroll view only allows scrolling on the left half of the screen (the whole view scrolls but your finger must be on the left side of screen to scroll). The Scroll View frame = (0 0; 320 431);.

If I go to another tab on my tab bar and return to this View the frame = (0 0; 480 320); what it is supposed to be and everything works/looks fine.

Any ideas what I need to do to get this by not selecting another tab and coming back?

EDIT

I made a subclass of Content View called ContentViewSubclass and put the following method in it:

-(CGSize)intrinsicContentSize{
CGSize size;
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
    size.height = 1000;
    size.width = 480;
    return size;
  }else{
    //iPhone Portrait
    size.height = 1000;
    size.width = 320;
    return size;
  }
}

Then on my ViewController.m I updated to the following code:

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[_contentView invalidateIntrinsicContentSize];
[_contentView intrinsicContentSize];
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{   _contentWidth.constant = 480;
    _contentHeight.constant = 1000;
}else{
    //iPhone Portrait
    _contentWidth.constant = 320;
    _contentHeight.constant = 1000;
  }
}

When I log the sizes I get

Landscape: ContentViewSubclass frame is (0 0, 480 1000) UIScrollView frame is (0 20, 480 251) contentView intrinsic size is {480, 1000}

Portrait: ContentViewSubclass frame is (0 0; 320 1000) UIScrollView frame is (0 20, 320 411) contentView intrinsic size is {320, 1000}

Everything is in a Tab Bar View Controller and here is what it is set up like:

  1. View
    • ScrollView
      • ContentView
      • Labels (many)
      • Textfields (many)
      • TableView (2)
      • CollectionViewSubcless (1)

I deleted the table views and Collection View in case they were causing problems and that didn't help.

Same issue. I get the correct layout on everything and it all scrolls, but you have be touching the left half of screen in landscape to scroll it. If I go to another tab view and return to this one it works correct. The scroll view then shows UIScrollView frame is (0 20, 480 300).

Upvotes: 3

Views: 2440

Answers (2)

wileedingo
wileedingo

Reputation: 1

I struggled with a similar situation. In my case it was the rightmost section of the landscape screen-width which is "added" to the portrait screen-width when rotated to landscape (i.e. for all values of x where: w-h < x <= w). Buttons and such which were constrained to move into that area were there, but were unresponsive. If that sounds the same as what you're seeing, then this simple solution might help. It fixed it for me.

Upvotes: 0

bilobatum
bilobatum

Reputation: 8918

You're using the "Pure AutoLayout Approach" described here by Apple in a Technical Note: https://developer.apple.com/library/ios/technotes/tn2154/_index.html

The "Pure AutoLayout Approach" works in Apple's sample code because an image view has an intrinsic content size; your content view, on the other hand, does not.

If you don't want to switch to the "Mixed Approach", then your content view will have to have an intrinsic content size. You do that by creating a UIView subclass and overriding the intrinsicContentSize method. In the willRotateToInterface… method, send invalidateIntrinsicContentSize to your content view.

Upvotes: 1

Related Questions