Определение максимального размера шрифта для многострочной UILabel с максимальной шириной - PullRequest
0 голосов
/ 19 сентября 2018

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

Я пытаюсь определить минимальный размер шрифта, необходимый для отображения message внутри UILabel из 3 строк, занимающего только maximumContentWidth ширину и со шрифтом UIFont.systemFont(.regular).Теперь я понимаю, что в UILabel есть свойства, которые позволяют ему автоматически уменьшаться, чтобы соответствовать размеру, который мне не подходит.Мне нужно определить конкретное число для минимального размера шрифта, чтобы применить его ко многим другим UILabels, некоторые из них отображают значительно меньше текста.

У меня максимальный размер шрифта составляет 20, а минимальный размер шрифта составляет13.

В настоящее время я частично использую решение, найденное здесь , однако оно работает только теоретически.Я не совсем уверен, почему, но когда я сделал какой-то тестовый текст, который был хорош для таких строк, как "fa fa fa ...", где fa повторяется до тех пор, пока я не узнаю визуально, что один fa не может вписаться в максимальный шрифт.Однако для таких строк, как "Ww wwwwwwwww wwww wwww ww wwww www w www www wwwwwww www wwwwwwww wwwwwww. Www wwwwwwww wwwwwww wwww www wwwwww www wwwwwwww www wwwwww wwww www 10000 wwww. Wwww ww ww ww, ww www www wwwwwwwwww www www wwwww wwwwwwwwwww www wwwwwwwwwwww. "система полностью выходит из строя, не делая текст таким маленьким, каким он должен быть.

Итак, вот детектор

extension UILabel {

    var isTruncated: Bool {

        guard let labelText = text else {
            return false
        }

        let labelTextSize = (labelText as NSString).boundingRect(
            with: CGSize(width: frame.size.width, height: .greatestFiniteMagnitude),
            options: .usesLineFragmentOrigin,
            attributes: [.font: font],
            context: nil).size

        return labelTextSize.height > bounds.size.height
    }
}

И вот как я его использую:

    var testLabel = UILabel()
    var font = 20
    testLabel.numberOfLines = 3
    testLabel.frame.size.width = maximumContentWidth
    while font > 13 {
        testLabel.text = message
        testLabel.font = UIFont.systemFont(ofSize: font, weight: .regular)
        testLabel.sizeToFit()
        if !testLabel.isTruncated {
            break
        }
        font -= 0.1
    }

Почему этот метод не работает и чем его можно заменить?

1 Ответ

0 голосов
/ 19 сентября 2018

Если я правильно понял ваш код, вы пытаетесь уменьшить размер шрифта, пока он не будет соответствовать размеру UILabel.Таким образом, размер шрифта будет максимально большим.

Основная проблема в цикле while.На каждом шаге вы устанавливаете новый font и вызываете sizeToFit, что заставляет вас поменять рамку, чтобы соответствовать размеру шрифта.После этого ваш isTruncated вернет false.

Вам нужно вручную установить фрейм UILabel s на каждом шаге, вместо того, чтобы вызывать sizeToFit().

testLabel.numberOfLines = 3
testLabel.text = message

while font > 13 {
    testLabel.font = UIFont.systemFont(ofSize: font, weight: .regular)
    testLabel.frame.size = CGSize(width: maximumContentWidth,
                                  height: maximumContentHeight)
    if !testLabel.isTruncated {
        break
    }
    font -= 0.1
}

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

ОБНОВЛЕНИЕ

Я не упомянул, что выхочу убедиться, что у вас UILabel не более 3 строк.Это немного сложно, потому что нет простого или простого способа узнать, сколько строк имеет UILabel.Но это решение, которое я использовал в своих проектах

extension UILabel {
    func getLinesCount() -> Int {
        let text = self.text ?? ""
        let rectWidth = self.frame.width

        let myFont = CTFontCreateWithName(font.fontName as CFString, font.pointSize, nil)
        let attStr = NSMutableAttributedString(string: text)
        let range = NSRange(location: 0, length: attStr.length)
        attStr.addAttribute(kCTFontAttributeName as NSAttributedStringKey, value: myFont, range: range)

        let frameSetter = CTFramesetterCreateWithAttributedString(attStr as CFAttributedString)
        let path: CGMutablePath = CGMutablePath()
        let rect = CGRect(x: 0, y: 0, width: rectWidth, height: CGFloat.greatestFiniteMagnitude)
        path.addRect(rect, transform: .identity)

        let frame: CTFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, nil)
        guard let lines = CTFrameGetLines(frame) as? [Any] else { return 0 }
        return lines.count
    }
}

Этот метод возвращает вам количество строк для вашего ярлыка на основе его font и width.Вы можете использовать его в цикле while, чтобы проверить, как он меняется.

Надеюсь, он вам поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...