Это отличный вопрос, и вы могли бы подумать, что использование максимально возможного размера шрифта без разбивки слов будет частью встроенной функциональности UIKit
или связанной с ней инфраструктуры. Вот хороший наглядный пример вопроса:
Как описано другими, хитрость заключается в том, чтобы выполнять поиск по размеру для отдельных слов, а также для всего текста в целом. Это связано с тем, что при указании ширины для рисования отдельных слов методы определения размера разбивают слова на части, поскольку у них нет другого выбора - вы просите их нарисовать «неразрывную» строку с определенным размером шрифта в регионе это просто не подходит.
В основе моего рабочего решения я использую следующую функцию двоичного поиска:
func binarySearch(string: NSAttributedString, minFontSize: CGFloat, maxFontSize: CGFloat, maxSize: CGSize, options: NSStringDrawingOptions) -> CGFloat {
let avgSize = roundedFontSize((minFontSize + maxFontSize) / 2)
if avgSize == minFontSize || avgSize == maxFontSize { return minFontSize }
let singleLine = !options.contains(.usesLineFragmentOrigin)
let canvasSize = CGSize(width: singleLine ? .greatestFiniteMagnitude : maxSize.width, height: .greatestFiniteMagnitude)
if maxSize.contains(string.withFontSize(avgSize).boundingRect(with: canvasSize, options: options, context: nil).size) {
return binarySearch(string: string, minFontSize:avgSize, maxFontSize:maxFontSize, maxSize: maxSize, options: options)
} else {
return binarySearch(string: string, minFontSize:minFontSize, maxFontSize:avgSize, maxSize: maxSize, options: options)
}
}
Одного этого недостаточно. Вы должны использовать его, чтобы сначала найти максимальный размер, который будет соответствовать самому длинному слову в границах. Как только вы это сделаете, продолжайте поиск меньшего размера, пока весь текст не уместится. Таким образом, ни одно слово никогда не будет разбито. Есть некоторые дополнительные соображения, которые немного более сложны, включая определение того, какое слово на самом деле длиннее (есть некоторые ошибки!), А также производительность кэширования шрифтов iOS.
Если вам нужно только показать текст на экране простым способом, я разработал надежную реализацию в Swift, которую я также использую в производственном приложении. Это подкласс UIView
с эффективным автоматическим масштабированием шрифта для любого вводимого текста, включая несколько строк. Чтобы использовать его, вы просто должны сделать что-то вроде:
let view = AKTextView()
// Use a simple or fancy NSAttributedString
view.attributedText = .init(string: "Some text here")
// Add to the view hierarchy somewhere
Вот и все! Вы можете найти полный исходный код здесь: https://github.com/FlickType/AccessibilityKit
Надеюсь, это поможет!