Question

I am trying to align an NSTextField and an NSImageView.. My current code is below. I have tried a bunch of different approaches including subclassing NSTextFieldCell (found here on SO), messing around with the frame of the text field, and tweaking constraints, but I just can't get it.. No matter what I do, it looks like the screenshot below..

I also have discovered that when I don't apply a font to the label, alignment works as I would expect -- it is vertically aligned with the image.

So the question is, a) why in the world does applying a font screw up the alignment, and b) how do I get around this, ideally in a dynamic way that will adapt if i change the font at runtime..

enter image description here

- (id)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    if (self) {
        NSView *spacer1 = [[NSView alloc] init];
        [spacer1 setTranslatesAutoresizingMaskIntoConstraints:NO];
        [self addSubview:spacer1];

        NSView *spacer2 = [[NSView alloc] init];
        [spacer2 setTranslatesAutoresizingMaskIntoConstraints:NO];
        [self addSubview:spacer2];

        NSImage *icon = [NSImage imageNamed:@"05-arrow-west"];
        NSImageView *iconView = [[NSImageView alloc] init];
        [iconView setTranslatesAutoresizingMaskIntoConstraints:NO];
        [iconView setImage:icon];

        [self addSubview:iconView];

        NSFont *font = [NSFont fontWithName:@"HelveticaNeue-Light" size:14];
        NSTextField *label = [[NSTextField alloc] init];
        [label setTranslatesAutoresizingMaskIntoConstraints:NO];
        [label setEditable:NO];
        [label setSelectable:NO];
        [label setBezeled:NO];
        [label setDrawsBackground:NO];

        [label setFont:font];
        [label setTextColor:[NSColor lightGrayColor]];
        [label setStringValue:@"Test String"];


        [self addSubview:label];

        NSDictionary *views = NSDictionaryOfVariableBindings(iconView, label, spacer1, spacer2);

        [self addConstraints:
                [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[spacer1(>=0)][iconView]-5-[label][spacer2(==spacer1)]|"
                                                        options: 0
                                                        metrics:nil
                                                          views:views]];

        [self addConstraints:
                [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[iconView]|"
                                                        options: 0
                                                        metrics:nil
                                                          views:views]];

        [self addConstraints:
                [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[label]|"
                                                        options: 0
                                                        metrics:nil
                                                          views:views]];

        [self setContentHuggingPriority:200 forOrientation:NSLayoutConstraintOrientationVertical];
        [iconView setContentHuggingPriority:200 forOrientation:NSLayoutConstraintOrientationVertical];
        [label setContentHuggingPriority:200 forOrientation:NSLayoutConstraintOrientationVertical];
    }

    return self;
}
Was it helpful?

Solution 2

In the end, this did it:

[self addConstraint:[NSLayoutConstraint constraintWithItem:label
                                                          attribute:NSLayoutAttributeBaseline
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:iconView
                                                          attribute:NSLayoutAttributeCenterY
                                                         multiplier:1
                                                           constant:0]];

OTHER TIPS

This is a very common problem related to AppKit calculating incorrect metrics for certain fonts. Helvetica Neue and its variants are susceptible to this problem. Autolayout depends on the intrinsicContentSize of the NSTextField, which uses broken metrics to calculate the appropriate size to display the text. The only way I know of to work around this problem is to use magic offsets in your layout constraints to manually align the text.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top