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

4
我有一个UIScrollView,其中包含一个UIView作为子视图。这个UIView垂直排列了一组数据条目——实际上只是一个固定格式的数据输入表单。
我希望保持UIView的垂直大小,并调整其水平大小以匹配UIScrollView的大小,后者会根据设备方向而变化。请注意,这一切都放在UISplitViewController的详细视图中。
因此,用户将需要垂直滚动,但不需要水平滚动,因为UIView上的所有文本字段都应自适应地调整大小以水平适应屏幕。
当前,如果我通过更改UIView的框架宽度来调整其大小以匹配UIScrollView的框架宽度,则UIView的子视图(文本字段)不会根据IB中设置的约束自适应调整大小。UIView似乎只被剪裁了。没有水平滚动,所以这方面的工作是正确的。
我已经在UIView和UIScrollView上设置了子视图自动调整大小。
你有什么提示?
还有,如果设备方向发生改变,我应该把调整UIView大小的代码放在哪里?
附加信息:
我在IB中创建了UIView作为同一个NIB中DetailViewController的一个单独视图。因为它比UIScrollView高得多,所以我在IB中找到的唯一方法就是将其设置为所需的宽度和高度的单独视图。然后,我创建一个IBOutlet,并在viewDidLoad方法中将此视图作为子视图添加到UIScrollView中。所有这些似乎都很好地工作了,除了UIView的子视图在水平方向上没有被调整大小。
你对我可能做错了什么有什么建议吗?

设置了哪些约束条件?这应该只需要使用自动布局就可以完成。 - Rakesh
你可能会认为我漏掉了什么。正如下面的Rakesh所指出的那样,UISCrollView和UIView(它的子视图)之间的约束没有设置,因为UIView在IB中不在UIScrollView中。我原以为只要通过改变UIView.frame来匹配UIScrollView的宽度来调整UIView的大小,但是如果我仅仅使用UIView.frame = newFrame,UIView不会调整其子视图的大小。 - Duncan Groenewald
也许我需要按照Rakesh下面的评论禁用自动布局。我会尝试这些建议并告诉你结果。 - Duncan Groenewald
Rakesh和我是同一个人。:D 无论如何,不要手动设置框架(如果您选择这种方式,则必须使用layoutSubviews来定位子视图),为什么不使用约束(以编程方式)也设置UIView,或者只需使用我在答案中提到的另一种方法? - Rakesh
我已经更新了答案,并提供了另一种选项。请查看。 - Rakesh
好的,现在它能工作了。我关闭了autoLayout,但这只是把一切都弄糟了,因为需要手动定位 - 这太费事了。再次打开时,我发现所有的限制都被移除了。所以我开始在viewDidLoad中添加以下内容:[self.scrollView addSubview:self.contentView]; self.scrollView.contentSize = self.contentView.frame.size; self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth; self.contentView.autoresizesSubviews = YES; - Duncan Groenewald
2个回答

3
由于您在xib中没有直接将视图放入scrollview中,因此IB不提供任何与父视图相关的约束选项。您可能需要通过编程方式添加约束。请参见这里编辑: 另外,尝试在视图上使用以下内容(根据文档,应该可以工作,但在自动布局方面不确定):
self.view.autoresizesSubviews = YES;

或者如果您不想使用自动布局,那么早期的方法是设置视图在大小检查器中扩展(水平/垂直)。为此,您必须禁用自动布局。选择xib->文件检查器->取消选中自动布局复选框。


1
嗯...我刚意识到它还没有完全正常工作。即使UIScrollView内部的UIView已经正确调整大小以匹配宽度,UIScrollView仍然水平滚动。似乎当我设置UIScrollView.contentSize时,它会记住这个值,并且不会根据UIView内部的任何调整而进行调整。如果我删除这行代码,那么就不会发生垂直或水平滚动(可能是因为contentSize为零)。因此,我认为UIScrollView不会根据其子视图的大小自动计算出其contentSize? - Duncan Groenewald
好的,我不得不在viewWillLayoutSubviews中添加以下代码来重置UIScrollView.contentSize。CGRect frame = self.contentView.frame; frame.size.width = self.view.frame.size.width; self.scrollView.contentSize = frame.size; - Duncan Groenewald
好的。我猜你需要单独设置contentView的大小。看看这些问题,它们可能会对你有所帮助。https://dev59.com/AXHYa4cB1Zd3GeqPQ99i和http://stackoverflow.com/questions/15034413/uiscrollview-and-constraints-issue - Rakesh
不,现在似乎contentView会自动正确调整大小。也就是说,它的宽度与scrollView相同,而高度保持不变。但我仍然困惑的是,scrollView.contentSize没有自动设置为子视图的大小。这是文档化的行为吗? - Duncan Groenewald
感谢其他问题/答案帮助确认我对事物运作方式的理解。 - Duncan Groenewald
好的,我想我刚刚找到了正确的方法来做我想做的事情,所以我觉得我应该在这里留个便条。 - Duncan Groenewald

3

在更多的探索后,我认为我已经找到了正确的方法来实现我想要做的事情,所以我觉得应该留下一条关于此的笔记。记住,我正在尝试创建一个可滚动的表单,它可以调整其宽度但不是高度,这样用户只需要上下滚动就可以访问字段。

  1. To create a large fixed size form that requires scrolling on the device make sure you set the ViewController size to Freeform in IB. Then you can create the view to be whatever size you want in IB and at runtime it will resize to the devices size.
  2. Place the UIScrollView (I call it the scrollView) in the main view and pin it left and right and top and bottom (i.e set constraints using IB)
  3. Place a UIView (I call it the contentView) in scrollView and make it the same size as the scrollView and also pin it on all sides to its superview (the scrollView)
  4. Now add all the labels and text fields are required to the contentView and make sure you add vertical constraints from top to bottom and left to right so that autolayout can figure out the width and height in order to calculate the scrollView.contentSize
  5. Set the contentView width constraint as a fixed size to make it look reasonable in IB. Bear in mind we want the width of contentView to always match the scrollView width so the user does not have to scroll sideways, only up and down. We will set the proper width in code at runtime as I have not found any way of doing this in IB only. Perhaps setting priorities on constraints might achieve this but I think UIScrollView won't do this for you.
  6. Now add a property the ViewController.h file and connect this to the contentView width constrain you created in 5) above.

    @property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewWidth;
    
  7. Finally create a viewDidLayoutSubviews method in ViewController and add the following code to set the contentView width to be the same as the scrollView width.

    - (void)viewDidLayoutSubviews
    {
        self.contentViewWidth.constant = self.scrollView.frame.size.width;
    
        [self.view layoutSubviews];
    }
    
  8. If things don't resize properly check all your constraints are correctly set. IB seems to do some things that seem strange to me. But finally I have it working with what appears to be minimum coding.

  9. You can also resize vertically in the same way as long as you set the constraint priority on subviews in contentView to be lower than 1,000. Also set a greater than or equal to size with a high priority if you don't want it smaller than a certain size.

如果有人能够仅使用IB约束设置contentView,使其自适应scrollView的宽度,我很想知道如何操作。


不要忘记 [super viewDidLayoutSubviews] :) - Adam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接