如何以编程方式将UIView大小设置为与父视图匹配,而不使用约束条件

21
这个问题听起来很简单,但是它让我发疯。 我在IB中创建了一个名为iBag的白色视图,并通过约束使其大小取决于屏幕大小。

enter image description here

现在我想通过编程方式创建一个新的 UIView,并使用以下代码将其添加为 iBag 的子视图,使其具有相同的大小和位置。
let newView = UIView()
newView.frame =  (frame: CGRect(x: 0, y: 0, width: iBag.frame.width, height: iBag.frame.height))
newView.backgroundColor = UIColor.redColor()
iBag.addSubview(newView)

enter image description here

我也尝试了边界,但是没有帮助。 我可以使用约束条件来解决问题,但我想理解出了什么问题。


2
你在 ViewWillAppear 中实例化新视图了吗? - Sandeep Bhandari
@SandeepBhandari 在viewDidLoad中 - Seifolahi
1
这是因为有限制。 - Er.Shreyansh Shah
3
viewDidLayoutSubviews方法中添加新视图,因为此时框架和自动布局过程尚未完成。请确保保留对新视图的引用,并仅在其为nil时才添加它,因为viewDidLayoutSubviews可能会被调用多次。 - Paulw11
将新视图的约束条件也以编程方式设置,那么它就可以工作了。 - Rukshan
显示剩余3条评论
10个回答

35

试一下这个:

Swift 1和2:

newView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]

Swift 3+:

newView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

如果不起作用,尝试这个:

iBag.autoresizesSubviews = true


29

有很多回答,但没有人解释问题在哪里。

我来试试。

在自动布局引擎开始确定其父视图的位置和大小之前,您将newView的框架设置为其父视图的框架。因此,当您使用superviews框架时,您使用的是它的初始框架。这在大多数情况下都是不正确的。

您有三种方法可以正确处理它:

  • 使用自动布局约束来处理newView

  • viewDidLayoutSubviews方法中设置newView的框架。该方法会在自动布局引擎完成确定框架的实际值时调用。(注意:此方法可能会被多次调用)

  • newView设置自动调整大小的掩码

1
谢谢你。你救了我的周末。 所有的教程都告诉我们如何格式化UIView,但没有人告诉我们必须在viewDidLayoutSubviews而不是viewDidLoad中调用update。 - user3729264

20
尝试这个:
子视图的框架大小与父视图一致。
子视图会相应地自动调整其尺寸以适应父视图的任何更改。
将子视图添加到父视图中。

4
也许这会对你有所帮助。
override func viewDidLayoutSubviews() {

    let newView = UIView()
    newView.frame = iBag.bounds
    newView.addConstraints(iBag.constraints)
    newView.backgroundColor = UIColor.redColor()
    iBag.addSubview(newView)

}

希望这能对你有所帮助。


抱歉,但仍然没有结果。 - Seifolahi
你在Storyboard中使用了自动调整大小或约束布局吗? - Nirav D
尝试了不同的方法后,它终于可以运行了,但只能在viewDidLayoutSubviews函数中运行。无论如何,谢谢你。 - Seifolahi

4
尝试这个:
 override func viewDidLayoutSubviews() {


    newView.frame =  (frame: CGRect(x: 0, y: 0, width: iBag.frame.width, height: iBag.frame.height))

}

或者您可以使用viewWillAppearviewDidAppear来设置框架。因为在viewDidLoad中,您的iBag框架与您的接口构建器(Storyboard)中相同。现在它将根据您运行的约束和设备大小进行更改。因此,在viewDidLoad中,您的新视图获取的是旧的未更改的框架。因此,最好使用viewDidLayoutSubviewsviewWilAppear
其次,无论何时都要么使用autolayout,要么不使用autolayout。在父视图中使用autolayout而不在子视图中使用是一种不好的做法。

那不是一个好的解决方案,因为viewDidLayoutSubviews会被多次调用。因此会创建许多“newViews”。 - jn-se
1
是的,没错 @jn-se 编辑了我的回答!现在应该没问题了。 - Ketan Parmar

1
也许这个会有效:-
subview.bounds.size = parentView.bounds.size

subview.center = parentView.center

但在您的情况下,CGRect内的widthheight应该是
width: parentView.bounds.size.width
height: parentView.bounds.size.height

然后将其作为子视图添加到其父视图中。

没有,结果一样。 - Seifolahi

0
如果您正在viewdidload中设置视图,请在viewdidappear中调用它,以便它可以根据屏幕大小捕获视图的原始框架。

0

不使用约束可能是问题所在。如果您的故事板/ Nib 设置为使用AutoLayout(默认情况下已启用),则设置框架/边界将被AutoLayout系统覆盖,您必须使用约束才能使布局正确显示。(或设置将自动调整大小掩码转换为约束的标志。我不记得该标志叫什么,目前也找不到它。)


0

试试这段代码:

let newView = UIView()
newView.frame =  (frame: CGRect(x: iBag.frame.origin.x, y: iBag.frame.origin.y, width: iBag.frame.size.width, height:  iBag.frame.size.height))
newView.backgroundColor = UIColor.redColor()
iBag.addSubview(newView)

-1
尝试使用 applyConstraints
parentView.addSubview(newSubview, applyConstraints: true)

根据文档,UIView.addSubview 只接受一个参数。文档链接:https://developer.apple.com/documentation/uikit/uiview/1622616-addsubview - jspizziri

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