cocoa - ¿Cómo dejar que NSTextField crezca con el texto en el diseño automático?
autolayout (3)
El diseño automático en Lion debería hacer que sea bastante simple dejar que un campo de texto (y, por lo tanto, una etiqueta) crezca con el texto que contiene.
El campo de texto está configurado para envolver el Constructor de interfaz.
¿Cuál es una forma simple y confiable de hacer esto?
Swift 4
Editar Autosizing NSTextField
Basado en la publicación Objective-C de Peter Lapisu
Subclase NSTextField
, agregue el código a continuación.
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()
}
Al establecer self.frame.size.height
en ''un número razonable'' se evitan algunos errores al usar FLT_MAX
, CGFloat.greatestFiniteMagnitude
o números grandes. Los errores se producen durante la operación cuando el usuario selecciona resalta el texto en el campo, puede arrastrar el desplazamiento hacia arriba y hacia abajo hasta el infinito. Además, cuando el usuario ingresa texto, NSTextField
se NSTextField
hasta que el usuario finaliza la edición. Finalmente, si el usuario ha seleccionado NSTextField
y luego intenta cambiar el tamaño de la ventana, si el valor de self.frame.size.height
es demasiado grande, la ventana se bloqueará.
La respuesta aceptada se basa en la manipulación de intrinsicContentSize
pero eso puede no ser necesario en todos los casos. El diseño automático aumentará y reducirá la altura del campo de texto si (a) le otorga al campo de texto el valor de MaxLayoutWidth preferredMaxLayoutWidth
y (b) no hace que el campo sea editable
. Estos pasos permiten que el campo de texto determine su ancho intrínseco y calcule la altura necesaria para el diseño automático. Vea esta respuesta y esta respuesta para más detalles.
Aún más oscuramente, se deduce de la dependencia en el atributo editable
del campo de texto que el autolayout se romperá si está utilizando enlaces en el campo y no borra la opción Conditionally Sets Editable
.
El método intrinsicContentSize
en NSView
devuelve lo que la vista en sí misma considera como su tamaño de contenido intrínseco.
NSTextField
calcula esto sin considerar la propiedad wraps
de su celda, por lo que informará las dimensiones del texto si se presenta en una sola línea.
Por lo tanto, una subclase personalizada de NSTextField
puede anular este método para devolver un mejor valor, como el proporcionado por el método cellSizeForBounds:
la celda:
-(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];
}