以下代码(在viewDidLoad中调用)会产生一个完全红色的屏幕。我希望它是一个完全绿色的屏幕。它为什么是红色的?我怎么能把它全部变成绿色呢?
UIScrollView* scrollView = [UIScrollView new];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
scrollView.backgroundColor = [UIColor redColor];
[self.view addSubview:scrollView];
UIView* contentView = [UIView new];
contentView.translatesAutoresizingMaskIntoConstraints = NO;
contentView.backgroundColor = [UIColor greenColor];
[scrollView addSubview:contentView];
NSDictionary* viewDict = NSDictionaryOfVariableBindings(scrollView,contentView);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics:0 views:viewDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|" options:0 metrics:0 views:viewDict]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[contentView]|" options:0 metrics:0 views:viewDict]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[contentView]|" options:0 metrics:0 views:viewDict]];
答案 0 :(得分:70)
滚动视图的约束与其他视图的约束略有不同。 contentView
及其superview
(scrollView
)之间的约束是scrollView
的{{1}},而不是contentSize
。这可能看起来令人困惑,但它实际上非常有用,这意味着您永远不必调整frame
,而contentSize
会自动调整以适合您的内容。 Technical Note TN2154中描述了此行为。
如果要在屏幕上定义contentSize
大小或类似大小,则必须在contentView
和主视图之间添加约束。不可否认,这与将内容放入滚动视图是对立的,所以我可能不会建议,但可以这样做。
为了说明这一概念,contentView
的大小将由其内容驱动,而不是由contentView
的{{1}}驱动,请为bounds
添加标签:
scrollView
现在,您会看到contentView
(以及UIScrollView* scrollView = [UIScrollView new];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
scrollView.backgroundColor = [UIColor redColor];
[self.view addSubview:scrollView];
UIView* contentView = [UIView new];
contentView.translatesAutoresizingMaskIntoConstraints = NO;
contentView.backgroundColor = [UIColor greenColor];
[scrollView addSubview:contentView];
UILabel *randomLabel = [[UILabel alloc] init];
randomLabel.text = @"this is a test";
randomLabel.translatesAutoresizingMaskIntoConstraints = NO;
randomLabel.backgroundColor = [UIColor clearColor];
[contentView addSubview:randomLabel];
NSDictionary* viewDict = NSDictionaryOfVariableBindings(scrollView, contentView, randomLabel);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics:0 views:viewDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|" options:0 metrics:0 views:viewDict]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[contentView]|" options:0 metrics:0 views:viewDict]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[contentView]|" options:0 metrics:0 views:viewDict]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[randomLabel]-|" options:0 metrics:0 views:viewDict]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[randomLabel]-|" options:0 metrics:0 views:viewDict]];
的{{1}})已调整为符合标准边距的标签。因为我没有指定标签的宽度/高度,所以会根据您放入该标签的文字进行调整。
如果您希望contentView
也调整到主视图的宽度,您可以像这样重新定义contentSize
,然后添加这些附加约束(除了所有其他约束之外,以上):
scrollView
滚动视图中有一个带有多行标签的known issue (bug?),如果您希望根据文本的数量调整大小,则需要做一些操作,例如:
contentView
答案 1 :(得分:1)
我试过Rob的答案一开始看起来很好。 但是!如果您还启用了缩放,则此Autolayout代码将受到阻碍。 在缩放时不断调整contentView的大小。也就是说,如果我放大(zoomScale> 1),我将无法滚动屏幕外的部分。
经过几天与Autolayout的斗争,遗憾的是我找不到任何解决方案。最后,它甚至不重要(扫管笏?好吧,对不起)。最后,我只是在contentView上删除了Autolayout(使用固定大小的contentView),然后在layoutSubviews中调整 self.scrollView.contentInset
。 (我正在使用Xcode5,iOS 7)
我知道这不是这个问题的直接解决方案。但我只想指出一个简单的解决方法。它完美地适用于在scrollView中居中固定大小的contentView,只需2行代码!希望它可以帮助某人;)
- (void)layoutSubviews {
[super layoutSubviews];
// move contentView to center of scrollView by changing contentInset,
// because I CANNOT set this with AUTOLAYOUT!!!
CGFloat topInset = (self.frame.size.height - self.contentView.frame.size.height)/2;
self.scrollView.contentInset = UIEdgeInsetsMake(topInset, 0, 0, 0);
}
答案 2 :(得分:-1)
通常,“自动布局”会将视图的顶部,左侧,底部和右侧边缘视为可见边缘。也就是说,如果将视图固定到其超视图的左边缘,则实际上将其固定到超视图边界的最小x值。更改超级视图的边界原点不会更改视图的位置。
UIScrollView类通过更改其边界的原点来滚动其内容。要使其与“自动布局”一起使用,滚动视图中的顶部,左侧,底部和右侧边缘现在表示其内容视图的边缘。
滚动视图子视图的约束必须导致填充大小,然后将其解释为滚动视图的内容大小。 (这不应与用于自动布局的intrinsicContentSize方法混淆。)要使用自动布局调整滚动视图的框架大小,约束必须明确关于滚动视图的宽度和高度,或者滚动视图的边缘必须是与其子树之外的视图相关联。
请注意,您可以通过在视图和滚动视图的子树外部的视图(例如滚动视图的超级视图)之间创建约束,使滚动视图的子视图显示为浮动(不滚动)在其他滚动内容上。
以下是两个如何配置滚动视图的示例,首先是混合方法,然后是纯方法