ios - 使用自动布局将动态大小的 View (高度)添加到 UIScrollView

标签 ios objective-c uiscrollview autolayout

这是我的详细 View 的 View 结构(博客应用程序,我想查看在 ScrollView 中具有动态高度的整个帖子):

UIView
  -UIScrollView
    -SinglePostView (custom view)
      -Title
      -Subtitle
      -Content

通常要将“单个帖 subview ”添加到 UIView 中,我只需将其实例化,将其提供给我的 Post 对象,然后添加一个将 singlePostView 的宽度固定到 super View 的约束,此时事情会得到很好的布局。但是,当我尝试将它添加到 ScrollView 时,它既不显示也不滚动。
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]];

最佳答案

在您使用 AutoLayout 呈现的结构中,contentSize您的 UIScrollViewintrinsicContentSize 驱动其 subview ,这里是您的 SinglePostView .

问题是,SinglePostViewUIView 的子类,其 intrinsicContentSize总是 CGSizeZero自己考虑的时候。您需要做的是制作intrinsicContentSize您的 SinglePostView取决于 intrinsicContentSize其 subview 。

然后,因为你的 SinglePostView 的 subview 是 UILabels ,并且因为 UILabelintrinsicContentSize是显示其内容所需的最小尺寸,您的 SinglePostViewintrinsicContentSize将等于其 subview 的总和 intrinsicContentSizes ,这是显示所有三个标签内容所需的总大小。

这是如何做到的。

步骤 1:删除所有自动设置的约束

首先,正如您部分所做的那样,您需要删除系统自动设置的所有约束。

假设您的 Storyboard或 XIB 中没有设置任何约束(或者您甚至没有其中之一),请执行以下操作:

scrollView.translatesAutoresizingMaskIntoConstraints  = NO;
singlePost.translatesAutoresizingMaskIntoConstraints = NO;
titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
contentLabel.translatesAutoresizingMaskIntoConstraints = NO;

现在您有一个清晰的 list ,您可以开始设置自己的约束条件。

第 2 步:约束 scrollView
首先,让我们像您一样创建供 AutoLayout 使用的 View 引用字典:
NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, singlePost, titleLabel, subtitleLabel, contentLabel);

然后,正如您已经做的那样,让我们​​将 ScrollView 限制为其超 View 的大小:
[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 步:约束 SinglePostViewscrollViewcontentSize
为了让这一步更清晰,您必须了解在 UIScrollView 之间设置的每个约束。和它的 subviews实际上会改变 contentSizeUIScrollView ,不是它的实际 bounds .例如,如果您约束 UIImageView到其父级的边界 UIScrollView然后放一张两倍大小的图片 UIScrollViewUIImageView ,您的图像不会缩小,它是 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与您的 scrollView 相同的。这样,您可以防止您的 scrollViewcontentSize.width不仅仅是它的 bounds.width .

第 4 步:约束您的 UILabels “插入”你的 SinglePostView
第四步也是最后一步,您现在需要对 SinglePostView 设置约束。的 subview ,以便它获得 intrinsicContentSize从他们。

这是您的操作方法(最简单的实现,没有边距,垂直一个接一个标签):
[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]];

这样你就应该完成了。

最后一个建议,你一定要看看 UIStoryboard做这些事情。它更简单,更直观。

希望这可以帮助,

P.S.:如果你愿意,我可以花一些时间同时使用 UIStoryboard 来插入一个项目。和 Visual Format Language在 Github 上。只要告诉我你是否需要一个。

祝你好运。

关于ios - 使用自动布局将动态大小的 View (高度)添加到 UIScrollView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24928514/

相关文章:

ios - 我如何设置一个计时器,使我的节点可以在 Swift Xcode 中每两秒跳转一次?

objective-c - 如何以编程方式打开 NSComboBox 的列表?

iphone - 使用 UIScrollView 用两根手指滚动

ios - SwiftUI中的.transition修饰符

c++ - Cocos2dx 中的像素完美碰撞检测

ios - 如何使用expectationForNotification

objective-c - 操作无法完成。 ( cocoa 错误 : 3840.)

iphone - "Attempt to create two animations for cell"ios 崩溃

ios - 使用两指平移和缩放对 UIScrollView 进行分页

ios - UIView 以编程方式设置约束