Je suis complètement dans le noir avec l'interligne de Core Text. J'utilise NSAttributedString et j'y spécifie les attributs suivants: - kCTFontAttributeName - kCTParagraphStyleAttributeName
CTFrameSetter est alors créé et dessiné dans un contexte.
Dans l'attribut de style de paragraphe, j'aimerais spécifier la hauteur des lignes.
Lorsque j'utilise kCTParagraphStyleSpecifierLineHeightMultiple, chaque ligne est complétée par un remplissage en haut du texte, au lieu du texte affiché au milieu de cette hauteur.
Lorsque j'utilise kCTParagraphStyleSpecifierLineSpacing, un remplissage est ajouté au bas du texte.
Aidez-moi à atteindre une hauteur de ligne spécifiée avec le texte (glyphes) au milieu de cette hauteur, au lieu du texte placé en bas ou en haut de la ligne.
N'est-ce pas possible sans aller dans le sens de la création explicite de CTLine et ainsi de suite?
Je ne suis toujours pas sûr à 100% de mes déclarations suivantes, mais cela semble logique. S'il te plaît, corrige-moi là où je me trompe.
La hauteur de ligne (interligne) fait référence à la distance entre les lignes de base des lignes de type successives. La ligne de base peut ici être interprétée comme la ligne imaginaire sur laquelle repose le texte.
L'espacement est l'espace entre les lignes. L'espace apparaît après la ligne de texte.
J'ai fini par utiliser la solution suivante à mon problème:
// 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;
Cette matrice est utilisée avec le paramètre de style de paragraphe pour 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*) ¶graphStyle, 3);
[attributedString addAttribute:(NSString*)kCTParagraphStyleAttributeName value:(id)style range:NSMakeRange(0, [string length])];
CFRelease(style);
J'espère que ça aide quelqu'un. Je mettrai à jour cette réponse à mesure que je découvrirai des informations plus pertinentes.
Vous pouvez l'utiliser si vous développez pour iOS> = 6.0
NSInteger strLength = [myString length];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setLineSpacing:24];
[attString addAttribute:NSParagraphStyleAttributeName
value:style
range:NSMakeRange(0, strLength)];
Dans 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]
Vous pouvez définir/mettre à jour l'espacement et la hauteur de ligne multiples à partir du storyboard ainsi que par programme.
De Interface Builder:
Par programme:
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
}
}
Appelez maintenant la fonction d'extension
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
Ou en utilisant une instance de label (il suffit de copier et d'exécuter ce code pour voir le résultat)
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
Il existe deux propriétés de NSParagraphStyle
qui modifient la hauteur entre les lignes de base de texte successives dans le même paragraphe: lineSpacing
et lineHeightMultiple
. @Schoob a raison de dire qu'une lineHeightMultiple
ci-dessus 1.0
ajoute un espace supplémentaire au-dessus du texte, tandis qu'une lineSpacing
ci-dessus 0.0
ajoute un espace sous le texte. Ce diagramme montre la relation entre les différentes dimensions.
Pour que le texte reste centré, l’objectif est donc de spécifier l’un en fonction de l’autre, de sorte que tout «remplissage» ajouté par un attribut (haut/bas) soit contrebalancé en déterminant le remplissage de l’autre attribut (bas/en haut) pour correspondre. En d'autres termes, tout espace supplémentaire ajouté est distribué de manière uniforme tout en préservant le positionnement existant du texte.
La bonne chose est que de cette façon, vous pouvez choisir l’attribut que vous voulez spécifier et ensuite déterminer l’autre:
extension UIFont
{
func lineSpacingToMatch(lineHeightMultiple: CGFloat) -> CGFloat {
return self.lineHeight * (lineHeightMultiple - 1)
}
func lineHeightMultipleToMatch(lineSpacing: CGFloat) -> CGFloat {
return 1 + lineSpacing / self.lineHeight
}
}
A partir de là, d'autres réponses montrent comment ces deux attributs peuvent être définis dans une variable NSAttributedString
, mais cela devrait indiquer comment les deux peuvent être associés au "centre" du texte.
Une autre façon de twerking avec une position de ligne NSAttributedString est de jouer avec baselineOffset attribut:
let contentText = NSMutableAttributedString(
string: "I see\nI'd think it`d be both a notification and a\nplace to see past announcements\nLike a one way chat.")
contentText.addAttribute(.baselineOffset, value: 10, range: NSRange(location: 0, length: 5))
contentText.addAttribute(.baselineOffset, value: -10, range: NSRange(location: 85, length: 20))
Résultat:
"Je vois
Je pense que ce serait à la fois une notification et une
endroit pour voir les annonces passées
Comme un chat à sens unique. "
Cela a fonctionné pour moi dans 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
}