Core Text-NSAttributedString altura de la línea ¿correcto?


Estoy completamente en la oscuridad con el interlineado del texto Principal. Estoy usando NSAttributedString y especifico los siguientes atributos en él: - kCTFontAttributeName - kCTParagraphStyleAttributeName

A partir de esto el CTFrameSetter se crea y se dibuja en contexto.

En el atributo de estilo de párrafo me gustaría especificar la altura de las líneas.

Cuando utilizo kCTParagraphStyleSpecifierLineHeightMultiple cada línea recibe relleno en la parte superior del texto, en lugar de la texto que se muestra en el centro de esta altura.

Cuando uso kCTParagraphStyleSpecifierLineSpacing se añade un relleno al final del texto.

Por favor, ayúdame a alcanzar una altura de línea especificada con el texto(glifos) en el medio de esa altura, en lugar del texto sentado en la parte inferior o superior de la línea.

¿No es esto posible sin ir por la ruta de crear explícitamente CTLine 's y así sucesivamente?

Author: Krunal, 2011-11-15

6 answers

Puedes usar esto si estás desarrollando para iOS > = 6.0

NSInteger strLength = [myString length];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setLineSpacing:24];
[attString addAttribute:NSParagraphStyleAttributeName
                  value:style
                  range:NSMakeRange(0, strLength)];
 86
Author: Tieme,
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
2013-05-02 12:21:14

Todavía no estoy 100% seguro de mis siguientes declaraciones, pero parece tener sentido. Por favor corrígeme donde estoy equivocado.

La altura de la línea (inicial) se refiere a la distancia entre las líneas de base de las líneas sucesivas de tipo. La línea de base aquí se puede interpretar como la línea imaginaria sobre la que se asienta el texto.

El espaciado es el espacio entre líneas. El espacio aparece después de la línea de texto.

Terminé usando la siguiente solución para mi problema:

// NOT SURE WHAT THE THEORY BEHIND THIS FACTOR IS. WAS FOUND VIA TRIAL AND ERROR.
    CGFloat factor = 14.5/30.5;
    CGFloat floatValues[4];
    floatValues[0] = self.lineHeight * factor/(factor + 1);
    floatValues[1] = self.lineHeight/(factor + 1);
    floatValues[2] = self.lineHeight;

Esta matriz se utiliza con el parámetro de estilo de párrafo para NSAttributedString:

CTParagraphStyleSetting paragraphStyle[3];

paragraphStyle[0].spec = kCTParagraphStyleSpecifierLineSpacing;
paragraphStyle[0].valueSize = sizeof(CGFloat);
paragraphStyle[0].value = &floatValues[0];

paragraphStyle[1].spec = kCTParagraphStyleSpecifierMinimumLineHeight;
paragraphStyle[1].valueSize = sizeof(CGFloat);
paragraphStyle[1].value = &floatValues[1];

paragraphStyle[2].spec = kCTParagraphStyleSpecifierMaximumLineHeight;
paragraphStyle[2].valueSize = sizeof(CGFloat);
paragraphStyle[2].value = &floatValues[2];

CTParagraphStyleRef style = CTParagraphStyleCreate((const CTParagraphStyleSetting*) &paragraphStyle, 3);
[attributedString addAttribute:(NSString*)kCTParagraphStyleAttributeName value:(id)style range:NSMakeRange(0, [string length])];
CFRelease(style);

Espero que esto ayude a alguien. Actualizaré esta respuesta a medida que descubra información más relevante.

 11
Author: Schoob,
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
2016-01-21 09:15:41

En Swift 3:

    let textFont = UIFont(name: "Helvetica Bold", size: 20)!
    let textColor = UIColor(white: 1, alpha: 1)      // White
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.paragraphSpacing = 20             // Paragraph Spacing
    paragraphStyle.lineSpacing = 40                  // Line Spacing

    let textFontAttributes = [
        NSFontAttributeName: textFont,
        NSForegroundColorAttributeName: textColor,
        NSParagraphStyleAttributeName: paragraphStyle
        ] as [String : Any]
 7
Author: Enrique,
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-04-25 18:19:40

Puede establecer/actualizar el espaciado de línea y la altura de línea múltiples desde storyboard, así como programáticamente.

Desde el creador de interfaces:

introduzca la descripción de la imagen aquí

Programáticamente:

SWift 4

extension UILabel {

    // Pass value for any one of both parameters and see result
    func setLineSpacing(lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) {

        guard let labelText = self.text else { return }

        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = lineSpacing
        paragraphStyle.lineHeightMultiple = lineHeightMultiple

        let attributedString:NSMutableAttributedString
        if let labelattributedText = self.attributedText {
            attributedString = NSMutableAttributedString(attributedString: labelattributedText)
        } else {
            attributedString = NSMutableAttributedString(string: labelText)
        }

        // Line spacing attribute

// Swift 4.2++


attributedString.addAttribute(NSAttributedString.Key.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))

// Swift 4.1--
attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))

        self.attributedText = attributedString
    }
}

Ahora llama a la función de extensión

let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"

// Pass value for any one argument - lineSpacing or lineHeightMultiple
label.setLineSpacing(lineSpacing: 2.0) .  // try values 1.0 to 5.0

// or try lineHeightMultiple
//label.setLineSpacing(lineHeightMultiple = 2.0) // try values 0.5 to 2.0

O usando la instancia label (Simplemente copie y ejecute este código para ver el resultado)

let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40

// Swift 4.2++
// Line spacing attribute
attrString.addAttribute(NSAttributedString.Key.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.characters.count))

// Character spacing attribute
attrString.addAttribute(NSAttributedString.Key.kern, value: 2, range: NSMakeRange(0, attrString.length))


// Swift 4.1--
// Line spacing attribute
attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.characters.count))

// Character spacing attribute
attrString.addAttribute(NSAttributedStringKey.kern, value: 2, range: NSMakeRange(0, attrString.length))

label.attributedText = attrString

Swift 3

let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
attrString.addAttribute(NSParagraphStyleAttributeName, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
label.attributedText = attrString
 5
Author: Krunal,
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-06-14 12:54:07

Esto funcionó para mí en Xcode 7.2. iOS 9.2.1. (Swift 2.1.):

  dispatch_async(dispatch_get_main_queue()) { () -> Void in
        let paragraphStyleWithSpacing           = NSMutableParagraphStyle()
        paragraphStyleWithSpacing.lineSpacing   = 2.0 //CGFloat
        let textWithLineSpacing                 = NSAttributedString(string: str, attributes: [NSParagraphStyleAttributeName : paragraphStyleWithSpacing])
        self.MY_TEXT_VIEW_NAME.attributedText   = textWithLineSpacing
    }
 0
Author: MB_iOSDeveloper,
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
2016-02-12 09:13:29

Hay dos propiedades de NSParagraphStyle que modifican la altura entre líneas de base de texto sucesivas en el mismo párrafo: lineSpacing y lineHeightMultiple. @Schoob tiene razón en que a lineHeightMultiple above 1.0 agrega espacio adicional por encima del texto, mientras que a lineSpacing above 0.0 agrega espacio por debajo del texto. Este diagrama muestra cómo se relacionan las diversas dimensiones.

Para conseguir que el texto permanezca centrado, el objetivo es especificar uno en términos del otro, de tal manera que cualquier 'relleno' agreguemos por un atributo (top / bottom) se equilibra determinando el relleno del otro atributo (bottom/top) para que coincida. En otras palabras, cualquier espacio adicional añadido se distribuye uniformemente mientras que de lo contrario preserva el posicionamiento existente del texto.

Lo bueno es que de esta manera puede elegir qué atributo desea especificar y luego determinar el otro:

extension UIFont
{
    func lineSpacingToMatch(lineHeightMultiple: CGFloat) -> CGFloat {
        return self.lineHeight * (lineHeightMultiple - 1)
    }

    func lineHeightMultipleToMatch(lineSpacing: CGFloat) -> CGFloat {
        return 1 + lineSpacing / self.lineHeight
    }
}

Desde aquí, otras respuestas muestran cómo estos dos atributos se pueden establecer en un NSAttributedString, pero esto debería responder cómo los dos pueden estar relacionado con 'centrar' el texto.

 0
Author: wardw,
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-07-18 18:45:28