How to force layoutSubviews of UIView?
Asked Answered
R

4

61

I have a custom UIView which has a dedicated, manually set frame for portrait and landscape orientation because autoresizingMasks just don't work in my case.

I set this frame in:

 - (void)viewWillAppear:(BOOL)animated

And it works as expected.

My problem is now, that my UIView furthermore has subviews that also have a dedicated position for portrait/landscape.

I position these subviews in:

- (void)layoutSubviews

If I now leave my viewController in e.g. portrait orientation, rotate to landscape on another viewController and then come back to this viewController I see that my view got resized correctly, but the subviews of my view, which get positioned in layoutSubviews are not repositioned yet but are resized in an animated fashion after the view already appeared.

I do nothing in viewDidAppear and I already tried calling

 - (void)layoutIfNeeded

As well as:

 - (void)setNeedsLayout

In viewWillAppear, but it doesn't seem to change anything.

Any ideas what I'm doing wrong?

Rudbeckia answered 27/9, 2011 at 14:3 Comment(0)
H
112

Had a similar problem today. I solved it by first calling

  • -setNeedsLayout: Set the flag that the view needs layout, and afterwards calling
  • -layoutIfNeeded: Check the flag immediately and - as it was set manually before - as result layoutSubviews is called.

Don't know if this is the best way, but it works ;)

Hollis answered 28/2, 2013 at 17:2 Comment(2)
this method seems to work better than just calling self.view.layoutSubviews()Calia
Calling layoutSubviews will use any constraints you have set to arrange the subviews. If what you're doing doesn't use constraints, you'll need to setNeedsLayout and then layoutIfNeeded to force a layout update immediately.Ugh
P
5

I would suggest setting the initial frame in viewDidLoad then changing the view frame for orientation changes in

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

You don't need any explicit animations in layoutSubviews (not sure if you had any, but it sounded like it) as any frame changes will be synced to the rotation animation.

When off screen the orientation should still be rotated, so your views should be positioned correctly when transitioned back on screen again.

I also recommend watching WWDC 2010 Session 123 "Building Animation Driven UI" which covers this stuff in much more detail.

Peursem answered 27/9, 2011 at 23:39 Comment(1)
I use willAnimateRotationToInterfaceOrientation for rotating my views while on-screen, and it works just fine. I also don't have a explicit animation in layoutSubviews, that's the problem. I don't animate the views explicitly, still they animate. "When off screen the orientation should still be rotated" .. really? never worked for me, I always had to reposition in viewWillAppear. Thanks for the tip with the Session though, will watch this session ASAP.Rudbeckia
D
5

At swift 3 @iOS 10.1

override func viewWillAppear(animated: Bool){

    super.viewWillAppear(animated)
    view.setNeedsLayout()
}

runs perfect

Didactics answered 23/11, 2016 at 17:39 Comment(1)
Apple: If you override this method, you must call super at some point in your implementation. So you should really call super, also if its working without.Giffie
N
-3

For me what worked is [self.view setNeedsDisplay] . This calls redraw on the whole view. You can also redraw a selected view by calling setNeedsDisplay on the particular view, which I did in my case and it worked perfectly.

Narration answered 28/4, 2015 at 13:4 Comment(1)
This causes the drawRect: method to be called instead.Frey

© 2022 - 2024 — McMap. All rights reserved.