添加动态调整视图(高度)与自动布局一个UIScrollView [英] Adding a dynamically sized view (height) to a UIScrollView with Auto Layout

查看:133
本文介绍了添加动态调整视图(高度)与自动布局一个UIScrollView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是我的意见对这个细节视图结构(博客应用程序,我想查看里面有动态的高度滚动视图内的整个后):

 的UIView
  -UIScrollView
    -SinglePostView(自定义视图)
      -标题
      -字幕
      -内容

通常为'单后视图添加到一个UIView我只是初始化它,喂它我的帖子对象,然后添加一个约束引脚singlePostView到上海华的宽度,在这一点的东西得到很好的布局。然而,当我尝试将其添加到滚动视图,它没有显示出来,也没有滚动。

 的UIScrollView滚动视图* = [[UIScrollView的页头]初始化];
[self.view addSubview:滚动视图]。NOBSinglePostView * singlePost = [[NOBSinglePostView页头] initWithPost:self.post];
[滚动视图addSubview:singlePost];
singlePost.translatesAutoresizingMaskIntoConstraints = NO;
scrollView.translatesAutoresizingMaskIntoConstraints = NO;*的NSDictionary = viewsDictionary NSDictionaryOfVariableBindings(滚动视图,singlePost);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@H:| [滚动视图] |选项​​:0的指标:0浏览:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@V:| [滚动视图] |选项​​:0的指标:0浏览:viewsDictionary]];
[滚动视图addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@H:| [singlePost] |选项​​:0的指标:0浏览:viewsDictionary]];


解决方案

在你是presenting,使用自动版式,在 contentSize 你的<$ C的结构$ C>的UIScrollView 是由 intrinsicContentSize 驱动,在这里你的 SinglePostView

问题是, SinglePostView 的UIView 的一个子类,它的 intrinsicContentSize 总是 CGSizeZero 时自行考虑。你需要做的是让 intrinsicContentSize 你的 SinglePostView 取决于 intrinsicContentSize 及其子视图。

然后,因为你的 SinglePostView UILabels ,并且因为的UILabel的子视图 intrinsicContentSize 是需要显示其内容的最小尺寸,你的 SinglePostView 小号 intrinsicContentSize 将等于它的子视图的总和 intrinsicContentSizes ,就是要显示的内容所需的总规模所有这三个的标签。

下面是如何做到这一点。

第1步:删除所有自动设置的限制

首先,你做的部分,你需要删除由系统自动设定的所有限制。

假设你没有在你的故事板或XIB设置任何限制(或者你甚至不必其中之一),只是做:

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

现在你有一个明确的石板,你可以开始设置自己的约束条件。

第二步:制约滚动视图

首先,让我们创建,像你一样,意见参考字典自动版式使用方法:

 的NSDictionary *意见= NSDictionaryOfVariableBindings(滚动视图,singlePost,titleLabel,subtitleLabel,内容标签);

然后,也因为你已经做了,让我们来限制滚动视图是它的父的大小:

  [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@H:| -0- [滚动视图] -0- |选项​​:0的指标:0浏览:观点]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@V:| -0- [滚动视图] -0- |选项​​:0的指标:0浏览:观点]];

第3步:制约 SinglePostView 滚动视图 contentSize

有关这一步是明确的,你要明白,一个的UIScrollView 子视图之间设置每个限制实际上将修改 contentSize 的UIScrollView ,并非其实际。例如,如果你限制一个的UIImageView 其父的UIScrollView 的边界,然后把图像大小的两倍在的UIScrollView 中的的UIImageView ,你的形象会不会被缩水,其的UIImageView ,将利用其图像的大小,并成为内滚动的的UIScrollView

因此​​,这里是你必须设置在这里是什么:

  [滚动视图addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@H:| -0- [singlePost] -0- |选项​​:0的指标:0浏览:观点]];
[滚动视图addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@V:| -0- [singlePost] -0- |选项​​:0的指标:0浏览:观点]];
[滚动视图addConstraint:[NSLayoutConstraint constraintWithItem:singlePost
                                                         属性:NSLayoutAttributeWidth
                                                         relatedBy:NSLayoutRelationEqual
                                                            toItem:滚动视图
                                                         属性:NSLayoutAttributeWidth
                                                        事半功倍:1.0F
                                                          恒:0.0];

前两个约束条件是pretty明显。第三个,但是,在这里,因为,你的 UILabels 来正确显示其内容,仍然是可读的,你可能会想他们能够multilined和滚动是垂直的,不是水平。这就是为什么你设置你的 SinglePostView 宽度来是一样的滚动视图的。这样,您prevent你的滚动视图 contentSize.width 比其<$ C什么都重要$ C> bounds.width

第4步:您的约束 UILabels 来推你的 SinglePostView

的界限

第四步也是最后一步,你现在需要你的 SinglePostView 子视图设置的限制,因此,它得到一个 intrinsicContentSize 从他们身上。

下面是你如何做到这一点(在最简单的实现,没有利润,一个标签其他垂直):

  [singlePost addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@H:| -0- [titleLabel] -0- |选项​​:0的指标:0浏览:观点]];
[singlePost addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@H:| -0- [subtitleLabel] -0- |选项​​:0的指标:0浏览:观点]];
[singlePost addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@H:| -0- [内容标签] -0- |选项​​:0的指标:0浏览:观点]];
[singlePost addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@V:| -0- [titleLabel] -0- [subtitleLabel] - [内容标签] -0- |选项​​:0的指标:0浏览:观点]];

和用您应该做的。

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

希望这有助于

PS:如果你愿意,我可以花一些时间,用推进项目既 UIStoryboard 视觉格式语言 Github上。只要告诉我,如果你需要的。

祝你好运。

Here is my structure of views for this detail view (blogging application, I want to view the entire post which has dynamic height inside of a scrollview):

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

Normally to add a 'single post view' to a UIView I simply instantiate it, feed it my Post object and then add a single constraint that pins the width of the singlePostView to the superview, at which point things get laid out nicely. However when I try to add it to a scroll view, it doesn't show up nor does it scroll.

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

解决方案

In the structure you are presenting, using AutoLayout, the contentSize of your UIScrollView is driven by the intrinsicContentSize of its subviews, here your SinglePostView.

The problem is, SinglePostView being a subclass of UIView, its intrinsicContentSize is always CGSizeZero when considered by itself. What you need to do is make the intrinsicContentSize of your SinglePostView depend on the intrinsicContentSize of its subviews.

Then, because the subviews of your SinglePostView are UILabels, and because a UILabel's intrinsicContentSize is the smallest size it needs to display its content, your SinglePostView's intrinsicContentSize will be equal to the sum of its subviews intrinsicContentSizes, that is the total size needed to display the content of all three of your labels.

Here is how to do it.

Step 1: Removing all automatically set constraints

First, as you partially did, you need to remove all constraints automatically set by the system.

Assuming you don't have any constraints set in your storyboard or XIB (or you don't even have one of these), just do:

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

Now you have a clear slate and you can start setting your own constraints.

Step 2: Constraining the scrollView

First, let's create, as you did, the views references dictionary for AutoLayout to use:

NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, singlePost, titleLabel, subtitleLabel, contentLabel);

Then, also as you already did, let's constrain the scroll view to be the size of its 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]];

Step 3: Constraining the SinglePostView to push the scrollView's contentSize

For this step to be clear, you have to understand that every constraints set between a UIScrollView and its subviews will actually change the contentSize of the UIScrollView, not its actual bounds. For Example, if you constrain a UIImageView to the borders of its parent UIScrollView and then put an image twice the size of the UIScrollView inside the UIImageView, your image won't get shrunk, its the UIImageView that will take the size of its image and become scrollable inside the UIScrollView.

So here is what you have to set here:

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

First two constraints are pretty obvious. The third one, however, is here because, for your UILabels to display their content properly and still be readable, you will probably want them to be multilined and the scrolling to be vertical, not horizontal. That's why you set your SinglePostView's width to be the same as your scrollView's. This way, you prevent your scrollView's contentSize.width to be anything more than its bounds.width.

Step 4: Constraining your UILabels to "push" the bounds of your SinglePostView

Fourth and final step, you now need to set constraints on your SinglePostView's subviews, so that it gets an intrinsicContentSize from them.

Here is how you do it (simplest implementation, no margins, one label after the other vertically):

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

And with that you should be done.

One last advice, you should definitely look into UIStoryboard to do these kinds of things. It's a lot simpler and more visual.

Hope this helps,

P.S.: If you want, I can take some time and push a project using both UIStoryboard and the Visual Format Language on Github. Just tell me if you would need one.

Good luck.

这篇关于添加动态调整视图(高度)与自动布局一个UIScrollView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆