¿Cómo dejar que NSTextField crezca con el texto en diseño automático?


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 ajustarse en Interface Builder.

¿Cuál es una forma sencilla y fiable de hacer esto?

Author: Monolo, 2012-05-05

3 answers

El método intrinsicContentSize en NSView devuelve lo que la vista misma piensa como su tamaño de contenido intrínseco.

NSTextField calcula esto sin considerar la propiedad wraps de su celda, por lo que reportará las dimensiones del texto si se presentan 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: de 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];
}
 44
Author: Monolo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-04 19:13:48

Swift 4

Autosizing editable NSTextField

Basado en el post 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()
}

Establecer self.frame.size.height a' un número razonable ' evita algunos errores al usar FLT_MAX, CGFloat.greatestFiniteMagnitude o grandes números. Los errores ocurren 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 introduce texto, NSTextField es borrado hasta que el usuario termine de editar. 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 colgará.

 3
Author: Lore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-12 17:36:57

La respuesta aceptada se basa en manipular intrinsicContentSize pero eso puede no ser necesario en todos los casos. El diseño automático crecerá y reducirá la altura del campo de texto si (a) le das al campo de texto un preferredMaxLayoutWidth y (b) haces que el campo no 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. Ver esta respuesta y esta respuesta para obtener más detalles.

Aún más oscuro, se desprende de la dependencia del texto el atributo editable del campo que el diseño automático se romperá si está utilizando enlaces en el campo y no borra la opción Conditionally Sets Editable.

 0
Author: spinacher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:30:56