Ios 使用自动布局将动态大小的视图(高度)添加到UIScrollView

Ios 使用自动布局将动态大小的视图(高度)添加到UIScrollView,ios,objective-c,uiscrollview,autolayout,Ios,Objective C,Uiscrollview,Autolayout,以下是我的详细视图视图结构(博客应用程序,我想查看整个文章,它在滚动视图中具有动态高度): 通常,要向UIView添加“单个post视图”,我只需实例化它,将其提供给我的post对象,然后添加一个约束,将单个PostView的宽度固定到superview,在这一点上可以很好地进行布局。但是,当我尝试将它添加到滚动视图时,它不会显示,也不会滚动 UIScrollView *scrollView = [[UIScrollView alloc] init]; [self.view addSubview

以下是我的详细视图视图结构(博客应用程序,我想查看整个文章,它在滚动视图中具有动态高度):

通常,要向UIView添加“单个post视图”,我只需实例化它,将其提供给我的post对象,然后添加一个约束,将单个PostView的宽度固定到superview,在这一点上可以很好地进行布局。但是,当我尝试将它添加到滚动视图时,它不会显示,也不会滚动

UIScrollView *scrollView = [[UIScrollView alloc] init];
[self.view addSubview:scrollView];

NOBSinglePostView *singlePost = [[NOBSinglePostView alloc] initWithPost:self.post];
[scrollView addSubview:singlePost];
singlePost.translatesAutoresizingMaskIntoConstraints = NO;
scrollView.translatesAutoresizingMaskIntoConstraints  = NO;

NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(scrollView,singlePost);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[singlePost]|" options:0 metrics: 0 views:viewsDictionary]];
在自动布局中

scrollview
的帧由
scrollview
scrollview
superview
之间的约束决定。
scrollview
contentSize
scrollview
scrollview
subview
之间的约束决定

您应该设置
singlePostView
的大小<代码>滚动视图从中计算
contentSize
。(需要明确添加尺寸约束)


在您使用AutoLayout呈现的结构中,
UIScrollView
contentSize
由其子视图的
intrinsicContentSize
驱动,这里是您的
SinglePostView

问题是,
SinglePostView
作为
UIView
的一个子类,其
intrinsicContentSize
在单独考虑时总是
CGSizeZero
。您需要做的是使
SinglePostView
intrinsicContentSize
依赖于其子视图的
intrinsicContentSize

然后,由于
SinglePostView
的子视图是
UILabel
,并且
UILabel
intrinsicContentSize
是显示其内容所需的最小大小,您的
SinglePostView
intrinsicContentSize
将等于其子视图
intrinsicContentSize
的总和,即显示所有三个标签内容所需的总大小

下面是如何做到这一点

步骤1:删除所有自动设置的约束 首先,正如部分操作一样,您需要删除系统自动设置的所有约束

假设您的故事板或XIB中没有设置任何约束(或者您甚至没有这些约束之一),只需执行以下操作:

scrollView.translatesAutoresizingMaskIntoConstraints  = NO;
singlePost.translatesAutoresizingMaskIntoConstraints = NO;
titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
contentLabel.translatesAutoresizingMaskIntoConstraints = NO;
现在,您有了一个清晰的计划,可以开始设置自己的约束

步骤2:约束
滚动视图
首先,让我们像您一样创建视图引用字典,以便AutoLayout使用:

NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, singlePost, titleLabel, subtitleLabel, contentLabel);
然后,正如您已经做的那样,让我们将滚动视图约束为其superview的大小:

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[scrollView]-0-|" options:0 metrics:0 views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[scrollView]-0-|" options:0 metrics:0 views:views]];
步骤3:约束
SinglePostView
以推送
scrollView
contentSize
为了明确这一步,您必须了解在
UIScrollView
及其
子视图之间设置的每个约束实际上会更改
UIScrollView
contentSize
,而不是其实际的
边界。例如,如果将
UIImageView
约束到其父级
UIScrollView
的边框,然后将一个大小为
UIScrollView
两倍的图像放在
UIImageView
内,则图像不会缩小,它是
UIImageView
,它将采用图像的大小,并在
UIScrollView
中可滚动

下面是您必须在这里设置的内容:

[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[singlePost]-0-|" options:0 metrics:0 views:views]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[singlePost]-0-|" options:0 metrics:0 views:views]];
[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:singlePost
                                                         attribute:NSLayoutAttributeWidth
                                                         relatedBy:NSLayoutRelationEqual
                                                            toItem:scrollView
                                                         attribute:NSLayoutAttributeWidth
                                                        multiplier:1.0f
                                                          constant:0.0f]];
前两个约束非常明显。然而,第三个原因是,为了使
UILabels
能够正确显示其内容并且仍然可读,您可能希望它们是多行的,并且滚动是垂直的,而不是水平的。这就是为什么要将
SinglePostView
width
设置为与
滚动视图的
相同。这样,您可以防止
滚动视图
contentSize.width
超出其
界限.width

步骤4:约束您的
ui标签
以“推”您的
SinglePostView的边界
第四步也是最后一步,您现在需要在
SinglePostView
的子视图上设置约束,以便它从中获得
intrinsicContentSize

下面是您的操作方法(最简单的实现,没有边距,一个标签接一个标签):

这样你就完了

最后一个建议是,要做这类事情,您一定要研究
UIStoryboard
。它更简单、更直观

希望这有帮助

注:如果你愿意,我可以花点时间,在Github上使用
UIStoryboard
可视格式语言
来推动一个项目。告诉我你是否需要一个


祝你好运。

如果在屏幕上显示singlePostView之前我不知道它的高度怎么办?您是说我需要手动计算高度本身(使用NSString+图像高度方法)?这似乎与自动布局的用途完全相反,如果内容视图具有固有大小(如UIImageView),则无需这样做。但如果不是,我认为内容大小需要计算。我将进行更多测试,以找出更好的解决方案。如果你已经找到了,请告诉我谢谢你的精彩描述。第3步,确保contentsize的宽度有界是缺失的link@Msencenb如果在iPhone4S上scrollView的高度缩小(宽度相同),该怎么办?我的结构与此相同,在ScrollView上有五个大小相同的UIView。用户只能水平滚动。它在iphone5、iphone6和iphone6plus上都能完美工作。然而,在iPhone4上,当scrollView的高度缩小(由于内容拥抱和内容抵制而故意缩小)时,我的UIView就不适合了。我必须垂直向下滚动才能看到整个图片,但这不是我想要的。我已经
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[scrollView]-0-|" options:0 metrics:0 views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[scrollView]-0-|" options:0 metrics:0 views:views]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[singlePost]-0-|" options:0 metrics:0 views:views]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[singlePost]-0-|" options:0 metrics:0 views:views]];
[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:singlePost
                                                         attribute:NSLayoutAttributeWidth
                                                         relatedBy:NSLayoutRelationEqual
                                                            toItem:scrollView
                                                         attribute:NSLayoutAttributeWidth
                                                        multiplier:1.0f
                                                          constant:0.0f]];
[singlePost addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[titleLabel]-0-|" options:0 metrics:0 views:views]];
[singlePost addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[subtitleLabel]-0-|" options:0 metrics:0 views:views]];
[singlePost addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[contentLabel]-0-|" options:0 metrics:0 views:views]];
[singlePost addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[titleLabel]-0-[subtitleLabel]-[contentLabel]-0-|" options:0 metrics:0 views:views]];