Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resize two subviews based on priorities using Cocoa Autolayout?

I am playing with Autolayout in Cocoa and some things are not clear for me.

I have 2 views on a window. The width of each view is 1/2 width of the parent window.

|           |           |
|           |           |
|   View1   |   View2   |
|           |           |
|           |           |

If I resize a window I want the View2 to resize first.

|           |     |
|           |     |
|   View1   |View2|
|           |     |
|           |     |

When View2 reaches its minimal size I want View1 to be resized to its minimal size.

|     |     |
|     |     |
|View1|View2|
|     |     |
|     |     |

How can I do that?

like image 495
Dmitry Avatar asked Jun 28 '12 12:06

Dmitry


1 Answers

The layout seems a bit unspecified. When does view2 start shrinking instead of matching view1's size? I am assuming that the views should be the same size until view1 reaches a soft minimum. At that point, view2 resizes until it reaches its minimum, and then view1 resizes until it reaches its minimum.

We can have this behavior by adding priorities to contraints. In order of importance we have:

  1. view1 and view2 >= minimum
  2. view1 >= view1SoftMinimum
  3. view1 == view2

Contraint 1 must be above the window resizing priority. We can make it required (which is the default).

Constraint 2 must be above contraint 3, but below NSLayoutPriorityDragThatCannotResizeWindow. We will make it 480.

Contraint 3 must be below contraint 2, so we make it 479.

We can express all of those contraints in one visual format string, which you can add

|[view1(>=view1Minimum,>=view1SoftMinimum@480,==view2@479)][view2(>=view2Minimum)]|

Here is the code I tested with:

NSView *view1 = [[NSTextView alloc] initWithFrame:NSZeroRect];
NSView *view2 = [[NSTextView alloc] initWithFrame:NSZeroRect];

[view1 setTranslatesAutoresizingMaskIntoConstraints:NO];
[view2 setTranslatesAutoresizingMaskIntoConstraints:NO];

NSView *contentView = [self.window contentView];

[contentView addSubview:view1];
[contentView addSubview:view2];

NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(view1, view2);

[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view1]|" options:NSLayoutConstraintOrientationVertical metrics:NULL views:viewsDictionary]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view2]|" options:NSLayoutConstraintOrientationVertical metrics:NULL views:viewsDictionary]];


NSDictionary *metrics = [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSNumber numberWithFloat:300], @"view1SoftMinimum",
                         [NSNumber numberWithFloat:150], @"view1Minimum",
                         [NSNumber numberWithFloat:150], @"view2Minimum", nil];

[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[view1(>=view1Minimum,>=view1SoftMinimum@480,==view2@479)]-[view2(>=view2Minimum)]|" options:0 metrics:metrics views:viewsDictionary]];
like image 134
Bridger Maxwell Avatar answered Sep 24 '22 14:09

Bridger Maxwell