Reputation: 3439
I've got a pair of editable text fields in a view using auto layout. (For completeness, these are inside an NSTableRowView
in an editable table, but I don't think that should matter.)
I'd like the fields to resize their width based on their content, especially once they are edited.
However, NSTextField
is not cooperating. I added some code to log the intrinsicContentSize
whenever the edit field ends editing, and the value is always { NSViewNoInstrinsicMetric, 15 }
, meaning the field has no intrinsic width.
I've seen a lot of posts about multi-line NSTextField
and vertical (height) resizing, wrapping, and so on, but I can't find any questions or answers that apply here. The fields are both set to "use single line", "clip", and "scroll".
I've tried sending the fields updateConstraints
and invalidateIntrinsicContentSize
messages, but they don't seem to have any effect.
I know I can create a subclass of NSTextField and hack this, but I don't understand why this isn't working in the first place. Or maybe NSTextField
simply doesn't have an intrinsic width, but I can't find that documented anywhere.
Note: previous answers to just set field.editable = NO
are insufficient; these fields must be editable.
Upvotes: 1
Views: 440
Reputation: 3439
Here's my hack:
//
// Create a special text field subclass that provides an intrinsic width for its content.
// Editable NSTextFields normally do not have an intrinsic width, because I guess that would just be too weird.
// This field returns an intrinsic width when not being edited, and the width of its superview when it is.
//
@interface ResizingPatternTextField : NSTextField
@end
@implementation ResizingPatternTextField
- (BOOL)becomeFirstResponder
{
BOOL willEdit = [super becomeFirstResponder];
if (willEdit)
[self invalidateIntrinsicContentSize];
return willEdit;
}
- (void)textDidEndEditing:(NSNotification*)notification
{
[super textDidEndEditing:notification];
[self invalidateIntrinsicContentSize];
}
- (NSSize)intrinsicContentSize
{
NSSize intrinsiceSize = super.intrinsicContentSize;
if (self.currentEditor!=nil)
{
// The field is currently being edited: return the width of the superview as the intrinsic width
// This should cause the field to expand to it's maximum width, within the constraints of the layout
intrinsiceSize.width = self.superview.bounds.size.width;
}
else
{
// If the field isn't being edited and it's editable: calculate the width of the field ourselves
if (self.editable)
{
NSDictionary* textAttrs = @{ NSFontAttributeName: self.font };
NSSize textSize = [self.stringValue sizeWithAttributes:textAttrs];
// Return an intrinsic size with a little padding, rounded up to the nearest whole integer
intrinsiceSize.width = CGCeiling(textSize.width+7.0);
}
}
return intrinsiceSize;
}
Notes:
CGCeiling
is just a macro for ceil()
Upvotes: 1