带有UIScrollview的iOS自动布局:为什么滚动视图的内容视图不能填充滚动视图?

2020/12/15 17:31 · ios ·  · 0评论

以下代码(在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]];

滚动视图的约束与其他视图的约束稍有不同。之间的约束contentView和其superview(所述scrollView)是对scrollViewcontentSize,而不是它的frame这看起来可能令人困惑,但实际上它非常有用,这意味着您不必调整contentSize,而是contentSize可以自动调整以适合您的内容。技术注释TN2154中描述了此行为

例如,如果要定义contentView屏幕尺寸或类似内容,则必须在contentView和主视图之间添加约束诚然,那是与将内容放入滚动视图相对的,所以我可能不建议这样做,但是可以做到。


为了说明这个概念,的大小contentView将由其内容决定,而不由的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]];

现在,您将看到contentView(以及因此contentSizescrollView)已调整为适合带有标准边距的标签。而且由于我未指定标签的宽度/高度,因此将根据您放入该标签的文本进行调整。


如果您还希望将contentView其调整为主视图的宽度,则可以viewDict像这样重新定义自己,然后添加这些其他约束(除了上述所有其他约束之外):

UIView *mainView = self.view;

NSDictionary* viewDict = NSDictionaryOfVariableBindings(scrollView, contentView, randomLabel, mainView);

[mainView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[contentView(==mainView)]" options:0 metrics:0 views:viewDict]];

滚动视图中的多行标签存在一个已知问题(错误?),如果您希望根据文本的数量来调整它的大小,则必须花些力气,例如:

dispatch_async(dispatch_get_main_queue(), ^{
    randomLabel.preferredMaxLayoutWidth = self.view.bounds.size.width;
});

一开始我尝试过Rob的答案看起来不错。但!如果您还启用了缩放功能,则此自动布局代码会妨碍您的操作。缩放时,它会继续调整contentView的大小。也就是说,如果放大(zoomScale> 1),将无法滚动屏幕外部的部件。

经过数天与Autolayout的斗争,可悲的是我找不到任何解决方案。最后,这甚至都没有关系(知道吗?好吧,对不起)。最后,我只是删除contentView上的Autolayout(使用固定大小的contentView),然后在layoutSubviews中调整 self.scrollView.contentInset(我正在使用Xcode5,iOS 7)

我知道这不是这个问题的直接解决方案。但我只想指出一个简单的解决方法。它仅需两行代码,即可完美地将固定大小的contentView定位在scrollView中。希望它可以帮助某人;)

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

通常,“自动布局”将视图的顶部,左侧,底部和右侧视为可见边缘。也就是说,如果将视图固定在其超级视图的左边缘,则实际上是将其固定在超级视图范围的最小x值。更改超级视图的边界原点不会更改视图的位置。

UIScrollView类通过更改其边界的原点来滚动其内容。为了使此功能与“自动布局”一起使用,滚动视图中的上,左,下和右边缘现在表示其内容视图的边缘。

滚动视图的子视图上的约束必须导致要填充的大小,然后将其解释为滚动视图的内容大小。(这不应与用于Auto Layout的internalContentSize方法混淆。)要使用Auto Layout调整滚动视图的框架大小,必须明确限制滚动视图的宽度和高度,或者必须将滚动视图的边缘设为绑定到其子树之外的视图。

请注意,可以通过在视图和滚动视图的子树外部的视图(例如,滚动视图的超级视图)之间创建约束,使滚动视图的子视图看起来漂浮(而不滚动)在其他滚动内容上。

这是两个如何配置滚动​​视图的示例,首先是混合方法,然后是纯方法

本文地址:http://ios.askforanswer.com/daiyouuiscrollviewdeioszidongbujuweishenmegundongshitudeneirongshitubunengtianchonggundongshitu.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!