2016-11-17 1 views
0

Когда я рисую привязанную строку с фиксированной высотой строки с помощью Text Kit, символы всегда выравниваются в нижней части фрагмента строки. Хотя это имеет смысл в одной строке с разными символами, это нарушает поток текста с несколькими строками. Исходные линии определяются самым большим descender для каждой линии.Выровнять базовые линии с символами в больших строках с помощью текстового набора

Я нашел article от людей за эскиз, объясняющих эту точную проблему в немного более подробно и показывая, что делает их решение, но, очевидно, не объясняя как они достигли этого.

Это то, что я хочу в принципе: bad: shifted baseline, good: baselines remain constant

При показе две строки с большой высоты строки, этот результат далек от идеала: characters not optically aligned

код я использую:

let smallFont = UIFont.systemFont(ofSize: 15) 
let bigFont = UIFont.systemFont(ofSize: 25) 
let paragraphStyle = NSMutableParagraphStyle() 
paragraphStyle.minimumLineHeight = 22 
paragraphStyle.maximumLineHeight = 22 
var attributes = [ 
    NSFontAttributeName: smallFont, 
    NSParagraphStyleAttributeName: paragraphStyle 
] 

let textStorage = NSTextStorage() 
let textContainer = NSTextContainer(size: CGSize(width: 250, height: 500)) 
let layoutManager = NSLayoutManager() 
textStorage.append(NSAttributedString(string: "It is a long established fact that a reader will be ", attributes:attributes)) 
attributes[NSFontAttributeName] = bigFont 
textStorage.append(NSAttributedString(string: "distracted", attributes:attributes)) 
attributes[NSFontAttributeName] = smallFont 
textStorage.append(NSAttributedString(string: " by the readable content of a page when looking at its layout.", attributes:attributes)) 

layoutManager.addTextContainer(textContainer) 
textStorage.addLayoutManager(layoutManager) 

let textView = UITextView(frame: self.view.bounds, textContainer:textContainer) 
view.addSubview(textView) 

ответ

1

Мне удалось получить эту работу, но, к сожалению, пришлось отказаться от поддержки iOS 8 и macOS 10.10.

Если вы реализуете следующий делегат зову NSLayoutManager, вы можете решить, что делать с baselineOffset для каждого фрагмента строки:

optional func layoutManager(_ layoutManager: NSLayoutManager, 
shouldSetLineFragmentRect lineFragmentRect: UnsafeMutablePointer<CGRect>, 
         lineFragmentUsedRect: UnsafeMutablePointer<CGRect>, 
          baselineOffset: UnsafeMutablePointer<CGFloat>, 
          in textContainer: NSTextContainer, 
        forGlyphRange glyphRange: NSRange) -> Bool 

Когда NSTextStorage создается и для каждого последующего изменения, я перечисляю все используемые шрифты, подсчитайте высоту линии по умолчанию (NSLayoutManager.defaultLineHeightForFont()) и сохраните самую большую высоту линии. При реализации вышеупомянутого метода делегата я проверяю текущую высоту строки NSParagraphStyle для предоставленного фрагмента строки и выравнивает высоту строки шрифта внутри этого значения. Оттуда смещение базовой линии можно рассчитать, зная, что базовая линия находится между шрифтом ascender и descender. Обновите значение baselineOffset с помощью baselineOffset.memory(newOffset), и все должно быть выровнено по вашему желанию.

Примечание: Я не слишком подробно расскажу о фактическом коде, используемом для реализации этого, потому что я не уверен, что использую правильные значения во всех этих вычислениях. Я могу обновить это в ближайшем будущем, когда весь подход будет проверен и проверен.

Обновление: Внедрение корректировки базовой линии. Каждый раз, когда меняет textContainer, я пересчитываю самую большую высоту линии и самый большой descender. Затем я в основном делаю это в функции делегата менеджера макета:

var baseline: CGFloat = (lineFragmentRect.pointee.height - biggestLineHeight)/2 
baseline += biggestLineHeight 
baseline -= biggestDescender 
baseline = min(max(baseline, 0), lineFragmentRect.pointee.height) 
baselineOffset.pointee = floor(baseline) 
+0

Можете ли вы разместить информацию? Мне любопытно, что вы с этим делаете. – ctietze

+1

Обновлено простой реализацией – Pim

Смежные вопросы