블로그 이미지
Sunny's

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

'layout'에 해당되는 글 1

  1. 2011.06.23 UIView 레이아웃 메커니즘의 이해 (sizeToFit 관련)
2011. 6. 23. 12:58 IPhone

Since I’ve just (hopefully) fully understood how on Earth the UIView layout mecanism works, I thaught I needed a note to re-read it as soon as I forget it!

The problem

Being able to call UIView’s -(void)sizeToFit to automagically layout a complex view tree like this one:

If you want this to be as simple as possible, you’ll need to call -(void)sizeToFit from the top level view (the blue one) – which will then call -(void)sizeToFit on the whole hierarchy (green, then yellow). I was stuck at first because I didn’t read carefully the Apple documentation for -(void)sizeToFit:

Resizes and moves the receiver view so it just encloses its subviews.

This means that we have a logical issue: we can’t call -(void)sizeToFit from top to bottom. If in the previous image, you take the 2nd green view which has two subviews that are not equals in height, you can’t determine the 2nd green view height without knowing the height used by its 2 children (the 2 yellow ones). And of course you can’t guess either the blue one’s height without knowing the 3 green height.

Summarized as:

If you want to lay out a parent view, you first need to lay out its children.

Methods we need to understand

UIView provides all the necessary methods to achieve this:

I had a hard time to figure out in which order I needed to call all these methods. Read carefully the code above, I’ve commented heavily so that you understand what it does. Right after, comes a schema which I hope is more meaningful.

@implentation YourCustomView
 
- (CGSize)sizeThatFits:(CGSize)size {
  // We use a vertical layout and thus place children
  // views in a vertical flow
  float y = 0.0f;
 
  for (UIView *subview in self.subviews) {
    // Each of the subviews needs to layout its own
    // subviews right now!
    [subview layoutIfNeeded];
    // Once subviews of THIS subview are in place we
    // can accordingly fit the size of the current subview
    [subview sizeToFit];
    // The subview has a new size
    CGRect frame = subview.frame;
    // We increment the y value (as in x,y axis)
    frame.origin.y = y;
    // Add whatever padding/margin you want to suits your
    // layout mecanism
    y += frame.size.height + kYourFunkyMarginBetweenViews;
  }
  // We finally have the size that fits self!
  size.height = y;
  return size;
}
 
// And we do almost the same exact thing
- (void)layoutSubviews {
  float y = 0.0f;
 
  for (UIView *subview in self.subviews) {
    [subview layoutIfNeeded];
    [subview sizeToFit];
    CGRect frame = subview.frame;
    frame.origin.y = y;
    // But this time we really move the subview to its
    // new place so that it doesn't overlaps its sibling
    // brothers and sisters.
    subview.frame = frame;
    y += frame.size.height + kYourFunkyMarginBetweenViews;
  }
}
 
@end

I made the following schema to stick my mind on it. I hope I have a well understanding of what’s going on under the hood.

So now you can call -(void)sizeToFit from your top level view ; it will go straight to the deepest level and lay out all the views from bottom to top.

[myTopView sizeToFit];

Hope this helps!

출처 : http://eddykudo.com/188

posted by Sunny's
prev 1 next