Centro de dos fuentes con diferentes tamaños verticalmente en un NSAttributedString


Utilizo NSAttributedString para generar una cadena con dos tamaños diferentes. Por defecto, su alineación inferior se ve así:

tamaños alineados con la línea de base

Pero quiero centrarlo verticalmente, así: tamaños centrados verticalmente

Para ser claros, esta es una sola cadena atribuida, no dos o más. Este es un ejemplo simplificado para describir mi pregunta, lo que realmente me gustaría hacer es más complejo.

Author: Tamás Sengel, 2013-10-21

4 answers

Diría que lo más fácil de hacer es manipular el atributo NSBaselineOffsetAttributeName para el texto en cuestión:

NSBaselineOffsetAttributeName

El valor de este atributo es un objeto NSNumber que contiene un valor de punto flotante que indica el desplazamiento del carácter desde la línea de base, en puntos. El valor predeterminado es 0.

Para centrar, tomarías la diferencia entre la altura del texto grande y la altura del texto más pequeño y la reducirías a la mitad, luego la usarías como base de referencia ajuste.

 80
Author: Ben Lachman,
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-11-05 01:47:27

Aquí hay un ejemplo de trabajo para alinear verticalmente texto más pequeño usando NSBaselineOffsetAttributeName.

NSString *bigString   = @"BIG";
NSString *smallString = @"Small String";
NSString *fullString = [NSString stringWithFormat:@"%@ %@", bigString, smallString];

NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:fullString];

NSRange bigStringRange = NSMakeRange(0, bigString.length);
NSRange smallStringRange = NSMakeRange(bigStringRange.length, smallString.length);

[string beginEditing];


//Set big string font and size
[string addAttribute:NSFontAttributeName
               value:[UIFont systemFontOfSize:28.0]
               range:bigStringRange];

//set small string font and size
[string addAttribute:NSFontAttributeName
               value:[UIFont systemFontOfSize:18.0]
               range:smallStringRange];

//Set small string baseline offset
[string addAttribute:NSBaselineOffsetAttributeName
               value:[NSNumber numberWithFloat:3.0]  //adjust this number till text appears to be centered
               range:smallStringRange];

[string endEditing];
 19
Author: Yas T.,
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-25 10:44:05

La mejor solución es calcular NSBaselineOffsetAttributeName a partir de tipografía de fuentes (artículo corto https://www.raizlabs.com/dev/2015/08/advanced-ios-typography/)

Establecer atributo para la segunda parte de la cadena atribuida.

secondPartAttributes[NSBaselineOffsetAttributeName] = @((firstFont.xHeight - secondFont.xHeight)/2);
 2
Author: Raman,
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-11-20 16:31:40

La respuesta de YaST {[4] } en Swift:

Swift 3

let bigString = "BIG"
let smallString = "Small String"
let fullString = "\(bigString) \(smallString)"
let string = NSMutableAttributedString(string: fullString)

let bigStringRange = NSRange(location: 0, length: bigString.utf16.count)
let smallStringRange = NSRange(location: bigStringRange.length, length: smallString.utf16.count)

let bigStringFontSize: CGFloat = 28
let smallStringFontSize: CGFloat = 18

string.beginEditing()

string.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: bigStringFontSize), range: bigStringRange)
string.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: smallStringFontSize), range: smallStringRange)
string.addAttribute(NSBaselineOffsetAttributeName, value: (bigStringFontSize - smallStringFontSize) / 2, range: smallStringRange)

string.endEditing()

Swift 4

let bigString = "BIG"
let smallString = "Small String"
let fullString = "\(bigString) \(smallString)"
let string = NSMutableAttributedString(string: fullString)

let bigStringRange = NSRange(location: 0, length: bigString.count)
let smallStringRange = NSRange(location: bigStringRange.length, length: smallString.count)

let bigStringFontSize: CGFloat = 28
let smallStringFontSize: CGFloat = 18

string.beginEditing()

string.addAttribute(.font, value: UIFont.systemFont(ofSize: bigStringFontSize), range: bigStringRange)
string.addAttribute(.font, value: UIFont.systemFont(ofSize: smallStringFontSize), range: smallStringRange)
string.addAttribute(.baselineOffset, value: (bigStringFontSize - smallStringFontSize) / 2, range: smallStringRange)

string.endEditing()
 0
Author: Tamás Sengel,
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-12-16 18:48:02