UIScrollView 具有自动布局的错误 contentSize

Posted

技术标签:

【中文标题】UIScrollView 具有自动布局的错误 contentSize【英文标题】:UIScrollView has wrong contentSize with auto layout 【发布时间】:2014-03-23 12:21:48 【问题描述】:

我在情节提要中有一个类似这样的 ios 屏幕:

如果我在模拟器中尝试此操作,我无法滚动到第二个 UIView(我使用分页)。我知道发生这种情况是因为 contentSize 的宽度为 320,但我不知道如何使用自动布局来解决它,也不知道如何让它在每个设备位置(横向、纵向)上工作。我只需要在 UIScrollView 中显示一个 UIView。谢谢。

【问题讨论】:

【参考方案1】:

这是可以解决的,应该可以很好地与自动布局一起使用。

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

如果您遇到问题,请告诉我。这种方式会有适应屏幕方向、屏幕大小、状态栏高度变化等的优势。

以上示例假设您要将孩子的高度设置为固定高度(80 像素)。要使其垂直填满屏幕,您宁愿执行与宽度相同的操作。

这还假设scrollviewsubview1subview2 都将其translatesAutoresizingMaskIntoConstraints 属性设置为NO

它也会在滚动视图中垂直对齐子视图。如果你想这样做,你可以让他们每个人都驻留在他们自己的 container 视图中,如下所示:

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

【讨论】:

谢谢。是否可以在 Interface Builder 中设置此约束? 我不确定您是否可以在界面构建器中拥有同样的灵活性【参考方案2】:

试试这样的:

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

关于自动布局:有时最好不要使用它们。

考虑屏幕方向的代码:

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

要捕捉设备旋转的那一刻,您应该在视图控制器中使用这种方法:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation

    // Remove current subviews

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

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

【讨论】:

我试过这样的东西,但这在横向模式下不起作用。 当然它不能在横向上工作,因为屏幕旋转 90 度,宽度和高度会相互替换。只需检查当前的屏幕方向。 其实你甚至不需要检查屏幕方向,它就足以获得屏幕的当前边界结构。我刚刚更新了答案中的代码。 我的意思是内容视图会有问题。您将能够在横向模式下同时看到多个 UIView。 当设备旋转时,您应该从 UIScrollView 中删除所有子视图,并用专门为当前屏幕方向调整大小的其他子视图填充它。

以上是关于UIScrollView 具有自动布局的错误 contentSize的主要内容,如果未能解决你的问题,请参考以下文章

具有自动布局和设备旋转的 UIScrollView

具有动态视图数量和自动布局 iOS6 的 UIScrollView

具有自动布局的 UIScrollView 中的动态大小的 UITableView

具有自动布局的 iOS UIScrollView 未正确居中

如何在具有自动布局的操作上自动增加 UIScrollView 中的内容大小?

UIView 无法在具有自动布局的 UIScrollView 中正确居中