Is there a UIView resize event?

IphoneIpadIos

Iphone Problem Overview


I have a view that has rows and columns of imageviews in it.

If this view is resized, I need to rearrange the imageviews positions.

This view is a subview of another view that gets resized.

Is there a way to detect when this view is being resized?

Iphone Solutions


Solution 1 - Iphone

As Uli commented below, the proper way to do it is override layoutSubviews and layout the imageViews there.

If, for some reason, you can't subclass and override layoutSubviews, observing bounds should work, even when being kind of dirty. Even worse, there is a risk with observing - Apple does not guarantee KVO works on UIKit classes. Read the discussion with Apple engineer here: https://stackoverflow.com/questions/6039309/when-does-an-associated-object-get-released

original answer:

You can use key-value observing:

[yourView addObserver:self forKeyPath:@"bounds" options:0 context:nil];

and implement:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (object == yourView && [keyPath isEqualToString:@"bounds"]) {
        // do your stuff, or better schedule to run later using performSelector:withObject:afterDuration:
    }
}

Solution 2 - Iphone

In a UIView subclass, property observers can be used:

override var bounds: CGRect {
    didSet {
        // ...
    }
}

Without subclassing, key-value observation with smart key-paths will do:

var boundsObservation: NSKeyValueObservation?

func beginObservingBounds() {
    boundsObservation = observe(\.bounds) { capturedSelf, _ in
        // ...
    }
}

Solution 3 - Iphone

Create subclass of UIView, and override layoutSubviews

Solution 4 - Iphone

Swift 4 keypath KVO -- This is how I detect autorotate and moving to iPad side panel. Should work work any view. Had to observe the UIView's layer.

private var observer: NSKeyValueObservation?

override func viewDidLoad() {
    super.viewDidLoad()
    observer = view.layer.observe(\.bounds) { object, _ in
        print(object.bounds)
    }
    // ...
}
override func viewWillDisappear(_ animated: Bool) {
    observer?.invalidate()
    //...
}

Solution 5 - Iphone

You can create a subclass of UIView and override the

setFrame:(CGRect)frame

method. This is the method called when the frame (i.e. the size) of the view is changed. Do something like this:

- (void) setFrame:(CGRect)frame
{
  // Call the parent class to move the view
  [super setFrame:frame];

  // Do your custom code here.
}

Solution 6 - Iphone

Pretty old but still a good question. In Apple's sample code, and in some of their private UIView subclasses, they override setBounds roughly like:

-(void)setBounds:(CGRect)newBounds {
    BOOL const isResize = !CGSizeEqualToSize(newBounds.size, self.bounds.size);
    if (isResize) [self prepareToResizeTo:newBounds.size]; // probably saves 
    [super setBounds:newBounds];
    if (isResize) [self recoverFromResizing];
}

Overriding setFrame: is NOT a good idea. frame is derived from center, bounds, and transform, so iOS will not necessarily call setFrame:.

Solution 7 - Iphone

If you're in a UIViewController instance, overriding viewDidLayoutSubviews does the trick.

override func viewDidLayoutSubviews() {
    // update subviews
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionlive-loveView Question on Stackoverflow
Solution 1 - IphoneMichalView Answer on Stackoverflow
Solution 2 - IphoneRudolf AdamkovičView Answer on Stackoverflow
Solution 3 - IphonegwangView Answer on Stackoverflow
Solution 4 - IphoneWarren StringerView Answer on Stackoverflow
Solution 5 - IphonerekleView Answer on Stackoverflow
Solution 6 - IphoneAdlai HollerView Answer on Stackoverflow
Solution 7 - IphoneDan RosenstarkView Answer on Stackoverflow