How can I programmatically position a view using relative points?
What is the best way to position a view relative to the size of its superview, when the bounds of the superview are not yet known?
I am trying to avoid hard-coding coordinates if it is at all possible. Perhaps this is silly, and if so, that's a perfectly acceptable answer.
I've run into this many times when working with custom UI. The most recent example is that I'm trying to replace the UINavigationItem
plain-text title with a custom view. I want that view to fill the superview, but in addition, I want a UIActivityIndicatorView
on the right side, inset about 2 pixels and centered vertically. Here's the code:
- (void) viewDidLoad
{
[super viewDidLoad];
customTitleView = [[UIView alloc] initWithFrame:CGRectZero];
customTitleView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
titleLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAut开发者_如何学JAVAoresizingFlexibleWidth;
titleLabel.lineBreakMode = UILineBreakModeWordWrap;
titleLabel.numberOfLines = 2;
titleLabel.minimumFontSize = 11.0;
titleLabel.font = [UIFont systemFontOfSize:17.0];
titleLabel.adjustsFontSizeToFitWidth = YES;
[customTitleView addSubview:titleLabel];
spinnerView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
spinnerView.center = CGPointMake(customTitleView.bounds.size.width - (spinnerView.bounds.size.width / 2) - 2,
customTitleView.bounds.size.height / 2);
spinnerView.hidesWhenStopped = YES;
[customTitleView addSubview:spinnerView];
self.navigationItem.titleView = customTitleView;
[customTitleView release];
}
Here's my problem: at the time that this code runs, customTitleView.bounds
is still zeroes. The auto-resizing mask hasn't had a chance to do its thing yet, but I very much want those values so that I can compute the relative positions of other sub-views (here, the activity indicator).
Is this possible without being ugly?
The only reason customTitleView.bounds has zero width and height is because you've initialized it that way by using CGRectZero. You can initialize the view with any nonzero size and then define its subviews in relation to that arbitrary size. As long as you've defined the autoresizing behaviors of the subviews properly, their layout will be adjusted appropriately when the frame of the superview changes at runtime.
For example:
- (void) viewDidLoad
{
[super viewDidLoad];
customTitleView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f)];
customTitleView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
titleLabel = [[UILabel alloc] initWithFrame:customTitleView.bounds];
titleLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
titleLabel.lineBreakMode = UILineBreakModeWordWrap;
titleLabel.numberOfLines = 2;
titleLabel.minimumFontSize = 11.0;
titleLabel.font = [UIFont systemFontOfSize:17.0];
titleLabel.adjustsFontSizeToFitWidth = YES;
[customTitleView addSubview:titleLabel];
[titleLabel release];
spinnerView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
spinnerView.center = CGPointMake(customTitleView.bounds.size.width - (spinnerView.bounds.size.width / 2) - 2,
customTitleView.bounds.size.height / 2);
spinnerView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
spinnerView.hidesWhenStopped = YES;
[customTitleView addSubview:spinnerView];
[spinnerView release];
self.navigationItem.titleView = customTitleView;
[customTitleView release];
}
精彩评论