I'm trying to set up an NSTextView
in an NSScrollView
programmatically and am having trouble.
Specifically, I can't scroll the text view; the scroll view seems to think "this is all there is". When you try to scroll down to see the rest of the content (without releasing), this is the result:
As soon as you release, the scroll view bounces back, so it's not a graphical glitch; it simply clips the text view at the frame height.
I've tried experimenting with the Apple 'Text In ScrollView' docs and I've experimented with setVerticallyResizable:
etc.
The code:
- (void)configureValueTextView
{
NSScrollView *vfContainer = [[NSScrollView alloc] initWithFrame:(NSRect){0,0,50,50}];
vfContainer.hasVerticalScroller = YES;
vfContainer.hasHorizontalScroller = NO;
vfContainer.translatesAutoresizingMaskIntoConstraints = NO;
_valueFieldContainer = vfContainer;
vfContainer.borderType = NSLineBorder;
NSTextView *valueField = _valueField = [[NSTextView alloc] initWithFrame:(NSRect){0,0,vfContainer.contentSize}];
valueField.delegate = self;
valueField.minSize = (NSSize){0,0};
valueField.maxSize = (NSSize){FLT_MAX, FLT_MAX};
[valueField setVerticallyResizable:YES];
[valueField setHorizontallyResizable:YES];
valueField.translatesAutoresizingMaskIntoConstraints = NO;
valueField.string = _value ? _value : @"";
valueField.editable = YES;
valueField.textContainer.containerSize = (NSSize) { vfContainer.contentSize.width, FLT_MAX };
valueField.textContainer.heightTracksTextView = NO;
vfContainer.documentView = valueField;
[vfContainer addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(0)-[_valueField]-(0)-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_valueField)]];
[vfContainer addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(0)-[_valueField]-(0)-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_valueField)]];
}
The frames are later adjusted to their right values,
[_valueFieldContainer setFrame:(NSRect){kKEFormFieldViewKeyWidth + 10, 0, valueFieldWidth, h}];
[_valueField setFrame:(NSRect){0, 0, valueFieldWidth, h}];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(0)-[_valueFieldContainer]-(5)-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_valueFieldContainer)]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(0)-[_keyField]-(10)-[_valueFieldContainer]-(0)-|" options:0 metrics:nil views:@{@"_keyField": _keyField, @"_valueFieldContainer": _valueFieldContainer}]];
And that's it. Hints welcome!
You've set a vertical constraint making the text view match the height of its superview (the clip view of the scroll view). I think that's what going wrong. If you just totally remove that, you've got complete ambiguity in the vertical direction and the text view can end up anywhere. I think you can get away with just pinning its top edge to the superview's top – i.e. @"V:|[_valueField]"
. That will work if the text view provides an intrinsic height, but I'm not sure it does. Setting up a constraint for the text view's height such that it matches what the text layout manager will produce is non-trivial.
Given that you don't really need anything special from the layout, you can just use the old-style autoresizing mask instead of auto layout.