简体   繁体   中英

UIScrollView has wrong contentSize with auto layout

I have a iOS screen in storyboard that look like that:

在此处输入图片说明

If I try this in simulator, I can't scroll to second UIView (I using paging). I know that this is happening because width of contentSize is 320, but I don't know ho to solve it using auto layout and I don't know how to make it work on every device position (landscape, portrait). I need to display only one UIView in UIScrollView. Thanks.

It is solvable and should work well with Auto Layout.

NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, subview1, subview2);

// Constraint the scrollview frame within its parent
[parentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
[parentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];

// Determine the scrollview's contentSize using its content
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[subview1]|" options:0 metrics: 0 views:viewsDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[subview1][subview2]|" options:0 metrics: 0 views:viewsDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[subview2]|" options:0 metrics: 0 views:viewsDictionary]];

// Set the children width using the outer view
[parentView addConstraint:[NSLayoutConstraint constraintWithItem:subview1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]];
[parentView addConstraint:[NSLayoutConstraint constraintWithItem:subview2 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]];

// Set the children height manually
[parentView addConstraint:[NSLayoutConstraint constraintWithItem:subview1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:80.0]];
[parentView addConstraint:[NSLayoutConstraint constraintWithItem:subview2 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:80.0]];

Tell me if you get issues. This approach will have the advantage of adapting to screen orientation, screen size, status bar height change, and so on.

The above example assumes you want to set the children's height to a fixed height (80 pixels). To make it fill the screen vertically, you would rather do the same as is done for width.

This also assumes scrollview , subview1 and subview2 all have their translatesAutoresizingMaskIntoConstraints property set to NO .

It will also not align the subviews vertically within the scrollview. If you wanted to do that, you could instead have each of them reside in their own container view like this :

// Set the containers' width & height using the outer view
[parentView addConstraint:[NSLayoutConstraint constraintWithItem:containerview1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]];
[parentView addConstraint:[NSLayoutConstraint constraintWithItem:containerview2 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]];

[parentView addConstraint:[NSLayoutConstraint constraintWithItem:containerview1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0]];
[parentView addConstraint:[NSLayoutConstraint constraintWithItem:containerview2 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0]];

// Set the children height manually
[containerview1 addConstraint:[NSLayoutConstraint constraintWithItem:subview1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:80.0]];
[containerview2 addConstraint:[NSLayoutConstraint constraintWithItem:subview2 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:80.0]];

// Align them vertically
[containerview1 addConstraint:[NSLayoutConstraint constraintWithItem:subview1 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:containerview1 attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]];
[containerview2 addConstraint:[NSLayoutConstraint constraintWithItem:subview2 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:containerview2 attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]];

// Set the width to equal that of their container
[containerview1 addConstraint:[NSLayoutConstraint constraintWithItem:subview1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:containerview1 attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]];
[containerview2 addConstraint:[NSLayoutConstraint constraintWithItem:subview2 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:containerview2 attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]];

Just try something like this:

[_scrollView setContentSize:CGSizeMake(640, _scrollView.frame.size.height)];

Regarding to autolayouts: sometimes it's better to get a rid of using them.

The code which considers screen orientation:

float screenWidth = [UIScreen mainScreen].bounds.size.width;
[_scrollView setContentSize:CGSizeMake(screenWidth * 2, _scrollView.frame.size.height)];

To catch the moment when device get rotated you should use such method within your view controller:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    // Remove current subviews

    for(UIView *subview in _scrollView.subviews)
    {
        [subview removeFromSuperview];
    }

    // Fill scroll view with subviews resized for screen size
    // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM