How to make a custom view resize with the window with Cocoa Auto Layout?

后端 未结 4 1226
野趣味
野趣味 2020-12-12 08:24

I have a single window with a single custom view in it, and I want the custom view to resize with the window so that it entirely fills it at any time. If I write:

         


        
4条回答
  •  情歌与酒
    2020-12-12 08:55

    With Auto Layout, there are (at least) three possible ways to constrain a view so that it occupies the entire window’s content view, resizing when appropriate.

    Visual format constraints with regard to superview

    NSView *contentView = [_window contentView];
    MyView *customView = [[MyView alloc] initWithFrame:[contentView bounds]];
    [customView setTranslatesAutoresizingMaskIntoConstraints:NO];
    
    [contentView addSubview:customView];
    
    NSDictionary *views = NSDictionaryOfVariableBindings(customView);
    
    [contentView addConstraints:
        [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[customView]|"
            options:0
            metrics:nil
            views:views]];
    
    [contentView addConstraints:
        [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[customView]|"
        options:0
        metrics:nil
        views:views]];
    

    Programmatic constraints for the edges

    (this should be equivalent to the visual format above)

    + (void)addEdgeConstraint:(NSLayoutAttribute)edge superview:(NSView *)superview subview:(NSView *)subview {
        [superview addConstraint:[NSLayoutConstraint constraintWithItem:subview
            attribute:edge
            relatedBy:NSLayoutRelationEqual
            toItem:superview
            attribute:edge
            multiplier:1
            constant:0]];
    }
    

    and

    NSView *contentView = [_window contentView];
    MyView *customView = [[MyView alloc] initWithFrame:[contentView bounds]];
    [customView setTranslatesAutoresizingMaskIntoConstraints:NO];
    
    [contentView addSubview:customView];
    
    [[self class] addEdgeConstraint:NSLayoutAttributeLeft superview:contentView subview:customView];
    [[self class] addEdgeConstraint:NSLayoutAttributeRight superview:contentView subview:customView];
    [[self class] addEdgeConstraint:NSLayoutAttributeTop superview:contentView subview:customView];
    [[self class] addEdgeConstraint:NSLayoutAttributeBottom superview:contentView subview:customView];
    

    Programmatic constraint for the size

    NSView *contentView = [_window contentView];
    MyView *customView = [[MyView alloc] initWithFrame:[contentView bounds]];
    [customView setTranslatesAutoresizingMaskIntoConstraints:NO];
    
    [contentView addSubview:customView];
    
    [contentView addConstraint:
        [NSLayoutConstraint constraintWithItem:customView
            attribute:NSLayoutAttributeWidth
            relatedBy:NSLayoutRelationEqual
            toItem:contentView
            attribute:NSLayoutAttributeWidth
            multiplier:1
            constant:0]];
    [contentView addConstraint:
        [NSLayoutConstraint constraintWithItem:customView
            attribute:NSLayoutAttributeHeight
            relatedBy:NSLayoutRelationEqual
            toItem:contentView
            attribute:NSLayoutAttributeHeight
            multiplier:1
            constant:0]];
    

    The third approach is the one listed in the question and it may not work if there are further constraints. For example, without:

    [customView setTranslatesAutoresizingMaskIntoConstraints:NO];
    

    the original autoresize mask is applied as well, which leads to the behaviour described in the question: the window isn’t resized.

    As mentioned by Regexident, you can use:

    [_window visualizeConstraints:[contentView constraints]];
    

    to debug Auto Layout. It’s worth checking the console output as well.

提交回复
热议问题