Will Smith
Will Smith

Reputation: 3

UIView width & height not adjusting to constraints

This is a question about iOS, XCode, Auto Layout, and Objective-C. I feel like it has an easy answer, but I've searched high and low in SO and can't find a solution.

I want to place a small crosshairs image in the center of a Google Map so that as the user pans around the map, the image remains fixed. I'm doing this by simply adding a UIImageView as a subview to the Google Map view, which is a GMSMapView that I've made an IBOutlet, self.mapView.

I calculate the location to place image with the following:

crosshairs.center = CGPointMake(self.mapView.bounds.size.width / 2, self.mapView.bounds.size.height / 2);

Meanwhile, I've set constraints on the map's view so that its leading and trailing spaces are pegged to the superview. That should make it's width and height liquid -- or so I thought.

In fact, when I NSLog the width and height of the map view at runtime, they reflect the width (600) and height (384) as specified in the size inspector in Xcode -- even though I have NOT pinned the width nor height with constraints.

The result is that the image is centered not to the screen, but to the map view's erroneous width and height (which extend off screen).

I know I'm overlooking something stupid, or I'm missing essential concepts of Auto Layout. Either way, I'd appreciate any guidance.

Will

Upvotes: 0

Views: 2852

Answers (1)

Catalina T.
Catalina T.

Reputation: 3494

The important thing while using auto layout, is you should not be changing the frame manually anymore (using setCenter: in your case). You should layout everything using constraints.

You could add the UIImage in the storyboard on top of the mapView and center it there, using constraints.

If that is not possible, you can also add the constraints in code, using something like this:

[self.mapView addSubview:crosshairs];
[crosshairs setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.mapView addConstraints:[NSLayoutConstraint constraintWithItem:self.mapView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:crosshairs attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0]];
[self.mapView addConstraints:[NSLayoutConstraint constraintWithItem:self.mapView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:crosshairs attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];

Depending on where you are adding these constraints, you might have to call [self.mapView layoutIfNeeded];.

Using the constraints, the image should always be centered on top of the mapView.

About the wrong frame for the mapView, it depends where you are logging it. If your IBOutlet is in a UIViewController, you should do it in viewWillLayoutSubviews: after the [super viewWillLayoutSubviews]; call.

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    NSLog(@"Map View frame %@", NSStringFromCGRect(self.mapView.frame));
}

If you have it in a custom UIView class, you should check the frame in layoutSubviews:

- (void)layoutSubviews {
    [super layoutSubviews];
    NSLog(@"Map View frame %@", NSStringFromCGRect(self.mapView.frame));
}

Hope this fixes your problem.

Upvotes: 1

Related Questions