Подтвердить что ты не робот

Центрируйте два шрифта разных размеров по вертикали в NSAttributedString

Я использую NSAttributedString для создания строки с двумя разными размерами. По умолчанию его нижнее выравнивание выглядит следующим образом:

baseline aligned sizes

Но я хочу сосредоточить его по вертикали, например: vertically centered sizes

Чтобы быть ясным, это единственная атрибутная строка, а не две или более. Это упрощенный пример для описания моего вопроса, что я действительно хотел бы сделать более сложным.

4b9b3361

Ответ 1

Я бы сказал, что проще всего манипулировать атрибутом NSBaselineOffsetAttributeName для рассматриваемого текста:

NSBaselineOffsetAttributeName

Значение этого атрибута - это объект NSNumber, содержащий значение с плавающей запятой, указывающее, что символы смещены от базовой линии в точках. Значение по умолчанию: 0.

Чтобы центрировать, вы должны понимать разницу между высотой большого текста и высотой меньшего текста и уменьшать его пополам, а затем использовать это как настройку базовой линии.

Ответ 2

Вот рабочий пример для вертикального выравнивания меньшего текста с помощью 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];

Ответ 3

Лучшее решение вычисляет NSBaselineOffsetAttributeName из типографики шрифтов (короткая статья https://www.raizlabs.com/dev/2015/08/advanced-ios-typography/)

Установить атрибут для второй части атрибутной строки.

secondPartAttributes[NSBaselineOffsetAttributeName] = @((firstFont.xHeight - secondFont.xHeight)/2);

Ответ 4

Ответ YasT в 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()