Автомакет в Lion должен сделать достаточно простым, чтобы текстовое поле (и, следовательно, ярлык) увеличивалось с сохраненным текстом.
Текстовое поле настроено на обертку в Interface Builder.
Что такое простой и надежный способ сделать это?
Автомакет в Lion должен сделать достаточно простым, чтобы текстовое поле (и, следовательно, ярлык) увеличивалось с сохраненным текстом.
Текстовое поле настроено на обертку в Interface Builder.
Что такое простой и надежный способ сделать это?
Метод intrinsicContentSize
в NSView
возвращает то, что сам взгляд рассматривает как его собственный размер содержимого.
NSTextField
вычисляет это без учета свойства wraps
своей ячейки, поэтому он будет сообщать размеры текста, если он выложен в одной строке.
Следовательно, пользовательский подкласс NSTextField
может переопределить этот метод, чтобы вернуть лучшее значение, например, предоставленное методом cell cellSizeForBounds:
:
-(NSSize)intrinsicContentSize
{
if ( ![self.cell wraps] ) {
return [super intrinsicContentSize];
}
NSRect frame = [self frame];
CGFloat width = frame.size.width;
// Make the frame very high, while keeping the width
frame.size.height = CGFLOAT_MAX;
// Calculate new height within the frame
// with practically infinite height.
CGFloat height = [self.cell cellSizeForBounds: frame].height;
return NSMakeSize(width, height);
}
// you need to invalidate the layout on text change, else it wouldn't grow by changing the text
- (void)textDidChange:(NSNotification *)notification
{
[super textDidChange:notification];
[self invalidateIntrinsicContentSize];
}
Основано на посте Питера Лапису Objective-C
Подкласс NSTextField
, добавьте код ниже.
override var intrinsicContentSize: NSSize {
// Guard the cell exists and wraps
guard let cell = self.cell, cell.wraps else {return super.intrinsicContentSize}
// Use intrinsic width to jive with autolayout
let width = super.intrinsicContentSize.width
// Set the frame height to a reasonable number
self.frame.size.height = 750.0
// Calcuate height
let height = cell.cellSize(forBounds: self.frame).height
return NSMakeSize(width, height);
}
override func textDidChange(_ notification: Notification) {
super.textDidChange(notification)
super.invalidateIntrinsicContentSize()
}
Установка self.frame.size.height
в "разумное число" позволяет избежать некоторых ошибок при использовании FLT_MAX
, CGFloat.greatestFiniteMagnitude
или больших чисел. Ошибки возникают во время работы, когда пользователь выбирает выделение текста в поле, они могут перетаскивать прокрутку вверх и вниз в бесконечность. Кроме того, когда пользователь вводит текст, NSTextField
отключается до тех пор, пока пользователь не завершит редактирование. Наконец, если пользователь выбрал NSTextField
и затем пытается изменить размер окна, если значение self.frame.size.height
слишком велико, окно будет зависать.
Принятый ответ основан на управлении intrinsicContentSize
, но это может быть не обязательно во всех случаях. Autolayout будет увеличиваться и уменьшать высоту текстового поля, если (a) вы даете текстовое поле a preferredMaxLayoutWidth
и (b) создаете поле не editable
. Эти шаги позволяют текстовому полю определять его внутреннюю ширину и вычислять высоту, необходимую для автоматического отключения. Подробнее см. этот ответ и этот ответ.
Еще более неясно, из зависимости от атрибута текстового поля editable
, что автоопределение будет нарушено, если вы используете привязки в поле и не можете очистить параметр Conditionally Sets Editable
.