UILabel расщепление в середине слов (или как получить правильную перенос слов) - PullRequest
0 голосов
/ 13 января 2019

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

  • соотношение сторон = 1: 1
  • label.width = 0.7 * parentView.width (все другие соответствующие ограничения установлены, ошибок или предупреждений в IB нет)

и следующий код:

    label.font = label.font.withSize(100)
    label.adjustsFontSizeToFitWidth = true
    label.lineBreakMode = .byClipping
    label.numberOfLines = 0
    label.text = "Shooter team"

Я бы надеялся, что он изменит размер текста и поместит его в две строки: «Стрелок» и «команда» (или, поскольку текст может быть чем угодно, правильно разделите его на слова). Тем не менее, когда я устанавливаю label.lineBreakMode на .byWordWrapping, он не изменяет размер текста вообще, поэтому отображается только одна большая буква (примечание: для изменения размера я использую большой размер шрифта, потому что не могу заранее знать, насколько большим будет текст, так как размер зависит от размера экрана). Любое другое значение для .lineBreakMode приводит к изменению размера текста, но разделяется на «Shoote» и «r team», что выглядит глупо. Изменение autoshrink например Minimum font size = 8, похоже, не имеет никакого эффекта. Смотрите скриншот ниже.

Любое предложение о том, как я могу получить правильное разбиение / изменение размера? Возможно, я использовал неправильные термины для своих поисков, но не нашел ответа: - |

(Примечание: возникнет другой вопрос о том, как я могу сделать границу охватывающего вида красивым кругом до отображения вида: - |)

Screenshot on iPhone 8+ simulator

Ответы [ 2 ]

0 голосов
/ 13 января 2019

Из-за отсутствия лучшего решения я написал следующую функцию, которая эмпирически пытается найти размер шрифта, который не разделяет слово в середине. Это хакерский, но, по крайней мере, он работает ... Комментарии, предложения или любое лучшее решение приветствуются!

func findFittingFont(for label: String) -> UIFont {
    // note: the 'split' function is a personal addition that splits a string on a regex
    // in this case, split between a non-word char and a word char
    let words = label.split(pattern: "(?<=\\W)(?=\\w)")
    var font = myLabel.font!
    // the width we don't want to overflow
    let maxWidth = myLabel.frame.width
    var fontSize = myLabel.frame.height
    var tooBig: Bool
    repeat {
        tooBig = false
        font = font.withSize(fontSize)
        // check for each word whether the rendered width is larger than the max width
        for word in words {
            // calculate the rendered width with the current font
            let width = (word as NSString).size(withAttributes: [.font: font]).width
            if width > maxWidth {
                tooBig = true
                // decrease the size by a factor
                fontSize *= 0.9
                break
            }
        }
        // go on as long as there's an overflowing word
    }
    while tooBig
    return font
}
0 голосов
/ 13 января 2019

Во-первых, чтобы воспользоваться adjustsFontSizeToFitWidth, вы также должны задать коэффициент масштабирования (наименьший размер, до которого вы хотите позволить этикетке сжаться). Так, если, например, шрифт вашей метки имеет размер 30, вы можете уменьшить его до 24:

someLabel.font = UIFont(name: "someFont", size: 30)
someLabel.adjustsFontSizeToFitWidth = true
someLabel.minimumScaleFactor = (24/30)

Во-вторых, вы можете рассмотреть возможность использования атрибутивного заголовка для вашего ярлыка, чтобы воспользоваться стилем абзаца. Стиль абзаца позволяет вам играть с правилами переноса слов:

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.hyphenationFactor = 1.0

let attributedTitle = NSAttributedString(string: "Shooter team", attributes: [NSAttributedString.Key.foregroundColor: UIColor.red, NSAttributedString.Key.paragraphStyle: paragraphStyle])

someLabel.attributedText = attributedTitle
...