Center custom UIView vertically and horizontally using Auto Layout

35,305

Solution 1

Try adding a height and width constraint to your circle_view. I couldn't even get just a pain square view to appear at all without adding those (using your code, minus the layer stuff).

NSLayoutConstraint *heightConstraint =
    [NSLayoutConstraint constraintWithItem:circle_view
                                 attribute:NSLayoutAttributeHeight
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:nil
                                 attribute:NSLayoutAttributeNotAnAttribute
                                multiplier:1.0
                                  constant:100.0];
    [circle_view addConstraint:heightConstraint];

    NSLayoutConstraint *widthConstraint =
    [NSLayoutConstraint constraintWithItem:circle_view
                                 attribute:NSLayoutAttributeWidth
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:nil
                                 attribute:NSLayoutAttributeNotAnAttribute
                                multiplier:1.0
                                  constant:100.0];
    [circle_view addConstraint:widthConstraint];

Solution 2

Just to add to rdelmar's answer:

The core issue is that as soon as you go the NSLayoutConstraint route, and specify setTranslatesAutoresizingMaskIntoConstraints:NO, the frame you made with CGRectMake is rendered irrelevant for AutoLayout purposes. That's why it didn't use the info from the frame's height and width.

Share:
35,305
phor2
Author by

phor2

Updated on July 29, 2020

Comments

  • phor2
    phor2 almost 4 years

    I'm trying to build a rather simple animated custom UI using the Auto Layout API newly available iOS 6. The custom view I'm building has a circle that I want to be both vertically and horizontally centered.

    Unfortunately I can't figure out why my constraints appear to work fine for UIButton, and UILabel elements but yield weird results when I use a custom view with and custom CALayer (in this case a circle, that will eventually be animated).

    To be clear I don't want my view to expand to fill the whole screen, but rather to have dynamic "padding" so that the view is vertically centered both on the iPhone 4 and 5. I should also note that I'm very new to Cocoa and UIKit.

    RootViewController.m:

    ...
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        // Create Circle View
        CGRect circle_view_rect = CGRectMake(0, 0, 100, 100);
        UIView *circle_view = [[UIView alloc] initWithFrame:circle_view_rect];
    
        // Create Circle Layer
        CircleLayer *circle_layer = [[CircleLayer alloc] init];
        circle_layer.needsDisplayOnBoundsChange = YES;
        circle_layer.frame = circle_view.bounds;
        [circle_view.layer addSublayer:circle_layer];
    
        // Enable Auto Layout
        [circle_view setTranslatesAutoresizingMaskIntoConstraints:NO];
    
        [self.view addSubview:circle_view];
    
        // Center Vertically
        NSLayoutConstraint *centerYConstraint =
        [NSLayoutConstraint constraintWithItem:circle_view
                    attribute:NSLayoutAttributeCenterY
                    relatedBy:NSLayoutRelationEqual
                       toItem:self.view
                    attribute:NSLayoutAttributeCenterY
                   multiplier:1.0
                     constant:0.0];
        [self.view addConstraint:centerYConstraint];
    
        // Center Horizontally
        NSLayoutConstraint *centerXConstraint =
        [NSLayoutConstraint constraintWithItem:circle_view
                    attribute:NSLayoutAttributeCenterX
                    relatedBy:NSLayoutRelationEqual
                       toItem:self.view
                    attribute:NSLayoutAttributeCenterX
                   multiplier:1.0
                     constant:0.0];
        [self.view addConstraint:centerXConstraint];
    }
    ...
    

    CircleLayer.m:

    ...
    - (void)drawInContext:(CGContextRef)context {
        CGContextAddArc(context, 50, 50, 50, 0.0, 2*M_PI, 0);
        CGContextSetFillColorWithColor(context, [UIColor yellowColor].CGColor);
        CGContextFillPath(context);
    }
    ...
    

    Basically the constraints I've implemented are:

    • center vertically inside parent view
    • center horizontally inside parent view

    And this is the result I get:

    Circle not centered with Auto Layout

    Any help would be greatly appreciated, I've been pondering this one for a few days now.

    Thanks

  • phor2
    phor2 over 11 years
    Thanks! That does exactly what I want. No more ambiguous layout warnings. :)
  • Mihail Velikov
    Mihail Velikov almost 9 years
    It took me a while until I understand that this code is an addition to the code from the question above. Thanks guys!
  • Eddie Deng
    Eddie Deng over 8 years
    this answer solved my problem. Even a frame is specified using initWithFrame: constructor, it is immediately invalidated upon calling etTranslatesAutoresizingMaskIntoConstraints:NO