How to set UIView size to match parent without constraints programmatically
Asked Answered
G

10

21

The problem sounds easy but it is making me crazy. I've created a white view in IB that's called iBag and by constraints it's size depends on screen size.

enter image description here

Now I want create a new UIView programmatically and add as subview to iBag with same size and position by this code

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

I also tried bounds but that didn't help. I can use constraints to solve the problem but i want to understand what's wrong.

Gown answered 9/6, 2016 at 12:0 Comment(8)
Where are you instantiating the new view in ViewWillAppear ???Electrograph
@SandeepBhandari In viewDidLoadGown
Can you try it in ViewDidAppear ????Electrograph
Use the code in viewWillAppear or viewDidAppear.Rarebit
This is because of constrains.Maenad
You should add the new view in viewDidLayoutSubviews as the frame & autolayout process won't be complete before then. Make sure you keep a reference to your new view and only add it if this is nil as viewDidLayoutSubviews may be called more than onceHiltan
set the new view's constraints programmatically too, then it will workDinner
@Paulw11Thank You. That's right.I should have known the issue.Gown
H
29

So many answers and nobody is explaining what's wrong.

I will try.

You are setting the frame of newView to your superviews frame before the autolayout engine has started to determine your superviews position and size. So, when you use the superviews frame, you are using its initial frame. Which is not correct in most cases.

You have 3 ways to do it correctly:

  • Use autolayout constraints for your newView

  • Set newViews frame in the viewDidLayoutSubviews method. Which is called when the autolayout engine finishes determining the frames actual values. (Note: This method can be called multiple times)

  • Set an autoresizing mask for newView
Hillery answered 9/6, 2016 at 12:22 Comment(1)
Thank you. You saved my weekend. All tutorials tells how to format UIView and no one tells that update must be called on viewDidLayoutSubviews instead of viewDidLoadLucent
C
35

Try this:

Swift 1 and 2:

newView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]

Swift 3+:

newView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

If it doesn't work, also this:

iBag.autoresizesSubviews = true

Corey answered 9/6, 2016 at 12:10 Comment(0)
H
29

So many answers and nobody is explaining what's wrong.

I will try.

You are setting the frame of newView to your superviews frame before the autolayout engine has started to determine your superviews position and size. So, when you use the superviews frame, you are using its initial frame. Which is not correct in most cases.

You have 3 ways to do it correctly:

  • Use autolayout constraints for your newView

  • Set newViews frame in the viewDidLayoutSubviews method. Which is called when the autolayout engine finishes determining the frames actual values. (Note: This method can be called multiple times)

  • Set an autoresizing mask for newView
Hillery answered 9/6, 2016 at 12:22 Comment(1)
Thank you. You saved my weekend. All tutorials tells how to format UIView and no one tells that update must be called on viewDidLayoutSubviews instead of viewDidLoadLucent
P
20

Try this

subview.frame = parentView.bounds

subview.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]

parentView.addSubview(subview)

Pemberton answered 9/6, 2016 at 12:13 Comment(0)
C
4

May be this will help you

override func viewDidLayoutSubviews() {

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

}

Hope this will help you.

Christopherchristopherso answered 9/6, 2016 at 12:11 Comment(3)
Sorry but still no resultGown
Are you using auto resize in storyboard or constraints layout?Christopherchristopherso
After trying different things it worked but it only works in viewDidLayoutSubviews function. Anyway Thank you.Gown
H
4

Try this,

 override func viewDidLayoutSubviews() {


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

}

or you can use viewWillAppear or viewDidAppear to set frame.

Because in viewDidload your iBag's frame is same which is in your interface builder (storyboard). Now it will change according to your constraints and device size on which you run. So, in viewDidload your new view get old frame not changed frame. So, it's better to use viewDidLayoutSubviews or viewWilAppear.

Second thing, Either use autolayout everywhere or nowhere. It is bad practice to use autolayout in parent view and not to child.

Hildie answered 9/6, 2016 at 12:28 Comment(2)
That is not a good solution because viewDidLayoutSubviews is called multiple times. So there will be many "newViews" created.Acescent
yeah that's right @Acescent Edited my answer! Now, it is fine i thinkHildie
M
1

may be this will work:-

subview.bounds.size = parentView.bounds.size

subview.center = parentView.center

but in your case, width and height inside the CGRect should be

width: parentView.bounds.size.width
height: parentView.bounds.size.height

and then add to it's parent as subview.

Myrmecophagous answered 9/6, 2016 at 12:4 Comment(1)
Nope , same result.Gown
W
0

try this code:

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)
Weinberg answered 9/6, 2016 at 12:12 Comment(0)
M
0

Not using constraints is likely what's wrong. If your storyboard/nib is set to use AutoLayout (which is on by default) then setting frames/bounds gets overridden by the AutoLayout system and you HAVE TO use constraints to get your layout to look right. (or set the flag that converts auto resizing masks to constraints. I don't remember what that flag is called and can't seem to find it at the moment.)

Mcripley answered 9/6, 2016 at 12:24 Comment(0)
E
0

If you are setting up your view in viewdidload, call it in viewdidappear, so it captures the original frame of view, accordingly to the screen size

Enthronement answered 17/4, 2019 at 2:21 Comment(0)
C
-1

Try use applyConstraints

parentView.addSubview(newSubview, applyConstraints: true)
Circuitous answered 25/9, 2020 at 17:58 Comment(1)
UIView.addSubview only accepts one parameter according to the documentation: developer.apple.com/documentation/uikit/uiview/…Luker

© 2022 - 2024 — McMap. All rights reserved.