tags:

views:

277

answers:

5

I've seen a bunch of similar questions to this, but nothing seems to be completely what I'm looking for. Do forgive me if I have missed the solution answered in another question, though!

Right. I have a view. 160 pixels both tall and wide. I know that this view is going to be used as a subview, and I know that it always needs to be centered about both axis in whatever situation it's used.

If defining the view programmatically, how can I be sure that it is always perfectly centered, horizontally and vertically, relative to its superview?

So far, all I have is this simple code:

- (void)loadView {
    self.view = [[UIView alloc] initWithFrame:CGRectMake(80, 150, 160, 160)];
    self.view.backgroundColor = [UIColor greenColor];
    self.view.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
    [self.view release];
}

This does the centralization, but only in the simplest of cases. Any insight is greatly appreciated.

EDIT 1:

With the addition of the following line of code:

 self.view.center = self.view.superview.center;

The subview's center point becomes the (0,0) coordinate of the superview. Perhaps I haven't set up the superview correctly?

+3  A: 

Assuming you are inside of a subclass of UIView, you could do this:

-(void) layoutSubviews {
  self.center = self.superview.center;
}

Or, if as above, you are working inside of a ViewController, you could

- (void)loadView {
//...
    self.view.center = self.view.superview.center;
}
Brad Smith
I don't this is correct. It will only work when your superview has it's top left corner at (0,0). See my solution below
pheelicks
Thanks for your response Brad. This really seems to be along the right lines, but I have run into another problem using this technique – perhaps the one which Pheelicks describes above.I have edited my original question with the details.
David Foster
A: 

Brad Smith beat me to the punch, with a slightly more elegant solution :D

Let me know if this isn't what you're looking for, but have you tried:

// when adding to a subview, try this, where myView is the view you need centered,
// and myMainView is the view you'll be adding it to as a subview
myView.center = myMainView.center;
[myMainView addSubview:myView];
Jasarien
+2  A: 

I'd say the simplest way to do this is to set the center of the view to be at the center of it's superview (which you can obtain from the superview's height and width attributes):

// Init as above and then...
// Get superview's CGSize
CGSize size = self.superview.frame.size;
[self.view setCenter:CGPointMake(size.width/2, size.height/2)];

I don't think you can do the simpler:

self.view.center = self.view.superview.center;

As the superview's center is defined in the superview's superview. Thus the superview could be centered about (0,0), but you wouldn't want to center your view at this point.

Quote from Apple docs:

The center is specified within the coordinate system of its superview

pheelicks
Your code will place the subview at the wrong position. The subview's center will be located at the bottom right corner of the superview. You need to divide the width and height values by 2 to get the center. Or you should just use the `center` property on `UIView`.
Jasarien
Forgot the divide by 2's. Good spot
pheelicks
+3  A: 

In addition to what @Jasarien and @Brad have said, don't forget that you can force auto-centering using the Autosizing springs and struts. Essentially (in Interface Builder) you click around until there are no Autosizing lines visible, like this:

alt text

In code, you set the -[UIView autoresizingMask] to:

(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin)

If you do these, then the view stays centered automatically.

EDIT #1

Answering your edit, you can't do:

self.view.center = self.view.superview.center;

Unless your view has been added as a subview of another view ([anotherView addSubview:self.view];). My guess is that self.view.superview is returning nil, and so you're (luckily) getting {0,0} as the return value when trying to invoke center on nil.

The proper place to center your view would probably be in the viewWillAppear: method of the view controller. Once the view is about to appear, you know that it must have a superview (otherwise how else would it be about to appear?). You could safely set your view's center there.

Dave DeLong
Dave, this is exactly what I was doing wrong! Silly, silly me, and thanks for pointing me to the solution. I'll have to give the correct answer to you on this one, although it must be said that Brad's and Pheelicks' contributions were mighty helpful too. Thanks again.
David Foster
A: 

I had the same issue. Each time I tried to access to self.view.superview or self.view.window on viewDidLoad they returned nil. In viewDidLoad (I guess it's the same for loadView) those pointer are not initialized yet. To solved this issue I can give you a trick:

- (void)viewDidLoad 
{
    [super viewDidLoad];

    // both equal to nil
    id lwindow = self.view.window;
    id lparent = self.view.superview;

    [self performSelector:@selector(myViewDidLoad) withObject:nil afterDelay:0.01];
}

- (void)myViewDidLoad
{
    // both not equal to nil!
    id lwindow = self.view.window;
    id lparent = self.view.superview;
} 

It's like self.view.parent and self.view.window are initialized after viewDidLoad and loadView.

ZeLegolas