如何调整 UIView 的大小并强制其子视图调整大小

Posted

技术标签:

【中文标题】如何调整 UIView 的大小并强制其子视图调整大小【英文标题】:How do I resize a UIView and force its subviews to resize 【发布时间】:2013-07-10 06:03:31 【问题描述】:

我有一个 UIScrollView 和一个 UIView 作为子视图。 UIView 有一堆垂直排列的数据输入字段——本质上只是一个固定格式的数据输入表单。

我想保持UIView's 的垂直大小并调整其水平大小以匹配UIScrollView 的大小,这取决于设备的方向。请注意,这都放在UISplitViewController 的详细信息视图中。

因此,用户必须垂直滚动而不是水平滚动,因为UIView 上的所有文本字段都应自行调整大小以适应屏幕水平。

目前,如果我通过更改框架宽度以匹配 UIScrollView's 框架宽度来调整 UIView 的大小,那么 UIView 子视图(文本字段)不会根据 IB 中的约束设置调整自身大小。 UIView 似乎被剪掉了。没有水平滚动,所以这方面工作正常。

我在UIViewUIScrollView 上设置了自动调整子视图。

关于在这里做什么的任何提示?另外,如果设备方向发生变化,我将在哪里放置代码来调整 UIView 的大小?

其他信息。

我在 IB 中创建了 UIView,作为与包含 UIScrollViewDetailViewController 相同的 NIB 中的单独视图。因为它比UIScrollView 高得多,所以我可以找到在 IB 中创建它的唯一方法是将其设置为所需宽度和高度的单独视图。然后,我创建一个 IBOutlet 并将此视图作为子视图添加到 viewDidLoad 方法中的 UIScrollView。除了UIView 子视图没有水平调整大小之外,这一切似乎都可以正常显示。

关于我在这里可能做错的任何建议?

【问题讨论】:

约束设置是什么?这应该可以通过自动布局来实现。 你会想,但很明显我错过了一些东西。正如下面的 Rakesh 指出的那样,未设置 UISCrollView 和 UIView(其子视图)之间的约束,因为 UIView 不在 IB 的 UIScrollView 内。我以为我可以通过更改 UIView 的框架以匹配 UIScrollView 的宽度来调整 UIView 的大小,但是如果我简单地使用 UIView.frame = newFrame,那么 UIView 不会调整其子视图的大小。 也许我需要按照下面 Rakesh 的评论禁用自动布局。我会尝试这些建议,让你知道我的进展。 Rakesh 和我,都是同一个人。 :D 无论如何,不​​要手动设置框架(如果你这样做,你也必须使用 layoutSubviews 来定位子视图),你为什么不设置 UIView 也使用约束(以编程方式)或者只是使用其他方式我在回答中提到过? 我也用另一个选项更新了答案。看看吧。 【参考方案1】:

由于您使用的是不直接从 xib 将视图放入滚动视图中,因此 IB 不提供选项来提供与超级视图有关的约束。您可能必须以编程方式添加约束。请参阅here。

编辑:

还可以尝试在视图上使用以下内容(尚未尝试,应该根据documentation 工作,但不确定是否使用自动布局):

self.view.autoresizesSubviews = YES;

或者,如果您根本不想使用自动布局,那么在尺寸检查器中将视图设置为展开(水平/垂直)的早期方法就可以了。为此,您必须禁用自动布局。选择 xib-> 文件检查器 -> 取消选中自动布局复选框

【讨论】:

嗯.. 我刚刚意识到它不是 100% 工作的。 UIScrollView 仍在水平滚动,即使其中的 UIView 大小正确匹配宽度。似乎当我设置 UIScrollView.contentSize 时,它​​会记住这一点,并且不会调整内部 UIView 的任何大小。如果我删除这行代码,则 n 不会垂直或水平滚动(可能是因为 contentSize 为零。我因此假设 UIScrollView 不会根据其子视图的大小自动计算出它的 contentSize ? OK 我必须将以下代码添加到 viewWillLayoutSubviews 以重置 UIScrollView.contentSize。 CGRect 框架 = self.contentView.frame; frame.size.width = self.view.frame.size.width; self.scrollView.contentSize = frame.size; 酷。我想你必须单独设置 contentView 的大小。检查这些问题,它可能会帮助你。 ***.com/questions/16441808/… 和 ***.com/questions/15034413/… 不,看来 contentView 现在会自动正确调整大小。也就是说,它的宽度与 scrollView 相同,并且高度保持不变。我仍然对 scrollView.contentSize 没有自动设置为子视图的大小感到困惑。这是记录在案的行为吗? 感谢其他问题/答案有助于确认我对事情如何运作的理解。【参考方案2】:

好的,经过更多的发现,我想我已经找到了正确的方法来做我想做的事情,所以我想我应该就此留下一个便条。请记住,我正在尝试创建一个可滚动的表单,它可以调整其宽度而不是其高度,因此用户只需上下滚动即可访问字段。

    要创建需要在设备上滚动的固定大小的大型表单,请确保在 IB 中将 ViewController 大小设置为 Freeform。然后,您可以在 IB 中将视图创建为您想要的任何大小,并在运行时将其调整为设备大小。 将 UIScrollView(我称之为 scrollView)放置在主视图中,并将其固定在左右和上下(即使用 IB 设置约束) 在 scrollView 中放置一个 UIView(我称之为 contentView),使其与 scrollView 的大小相同,并将其固定在其父视图(scrollView)的所有侧面 现在将所有需要的标签和文本字段添加到 contentView 并确保从上到下和从左到右添加垂直约束,以便自动布局可以计算出宽度和高度以计算 scrollView.contentSize 将 contentView 宽度约束设置为固定大小,使其在 IB 中看起来合理。请记住,我们希望 contentView 的宽度始终与 scrollView 宽度相匹配,这样用户就不必横向滚动,只需上下滚动即可。我们将在运行时在代码中设置适当的宽度,因为我还没有在 IB 中找到任何这样做的方法。也许在约束上设置优先级可能会实现这一点,但我认为 UIScrollView 不会为你做到这一点。

    现在在 ViewController.h 文件中添加一个属性并将其连接到您在上面 5) 中创建的 contentView 宽度约束。

    @property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewWidth;
    

    最后在ViewController中创建一个viewDidLayoutSubviews方法,添加如下代码设置contentView的宽度和scrollView的宽度一样。

    - (void)viewDidLayoutSubviews
    
        self.contentViewWidth.constant = self.scrollView.frame.size.width;
    
        [self.view layoutSubviews];
    
    

    如果没有正确调整大小,请检查您的所有约束是否设置正确。 IB似乎做了一些我觉得很奇怪的事情。但最后我让它使用似乎是最低限度的编码。

    你也可以用同样的方法垂直调整大小,只要你在 contentView 中设置 subview 的约束优先级低于 1000。如果您不希望它小于某个大小,还可以设置一个具有高优先级的大于或等于大小。

如果有人能弄清楚如何设置 contentView 以便它调整其宽度以仅使用 IB 约束匹配滚动视图,我很想知道如何。

【讨论】:

别忘了 [super viewDidLayoutSubviews] :)

以上是关于如何调整 UIView 的大小并强制其子视图调整大小的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Autolayout 调整我的超级视图大小以匹配其子视图的大小?

创建后调整uiview子类的大小

如何调整视图大小以使其子视图也调整大小

如何调整视图的大小,同时按比例调整其子视图的大小?

使用UIToolbar调整UIView的大小不会同时调整大小

UIView 调整内容大小