SwiftUI Word Wrap для многострочного текста Проблема расстановки переносов в словах

Я столкнулся со следующей проблемой с SwiftUI Text: В следующем примере SwiftUI разбивает слово "Amazement" на "amazeme" в первой строке и "nt" во второй. Как этого избежать, не баг?

Я хочу, чтобы слово "изумление" было написано в одну строку. Есть ли какой-нибудь модификатор, позволяющий это (не разделять слова или что-то в этом роде)?

Пробовал.allowsTtening, .fixedSize. Изменен порядок модификаторов, не помогло.

Это ошибка или у нас пока нет возможности исправить это? Решение должно работать для каждой строки, а не только для указанной строки.

Вы можете воспроизвести поведение, используя этот код:

        struct TestView2: View {
    var body: some View {
        ZStack {
        Text("Amazement Awaits us at every corner")
           
            .font(.system(size: 160))
            .foregroundColor(.blue)
            .foregroundColor(.white)
            .lineLimit(4)
            .multilineTextAlignment(.leading)
            .minimumScaleFactor(0.01)
            //.allowsTightening(true)
            //.fixedSize(horizontal: false, vertical: true)
      
        }
    }
}
    
    struct TestView2_Previews: PreviewProvider {
        static var previews: some View {
            TestView2()
        }
    }

3 ответа

Похоже, что перенос слов по символу используется по умолчанию, когда дело доходит до размещения текста в представлении. я нашел это .minimumScaleFactorработает только в том случае, если система не может вместить текст (с разрывами символов). Если это не сработало, он попытается уменьшить масштаб текста. Если попытаться уменьшить linelimitтогда minimumScaleFactorсработает и попытается уменьшить текст, пока он не уместится.

На данный момент я использую хак, где я проверяю количество символов слов в тексте, если в каком-либо слове больше символов, чем определенный порог, я уменьшаю размер шрифта, в противном случае я использую размер по умолчанию.

      struct TestView2: View {
    let text: String
    var body: some View {
        ZStack {
            Text(self.text)
                .font(.system(size: self.getSizeForText(self.text)))
                .foregroundColor(.blue)
                .foregroundColor(.white)
            .lineLimit(4)
            .multilineTextAlignment(.leading)
            .minimumScaleFactor(0.01)
            //.allowsTightening(true)
            //.fixedSize(horizontal: false, vertical: true)
        }
    }
    
    private fund getSizeForText(_ text: String) -> Double {
        let CHARS_THRESHOLD = 12 // change this as needed
        let words = text.split(separator: " ")
        if words.contains(where: { $0.count > CHARS_THRESHOLD }) {
            // text contains a long word, decrease the font size
            return 150.0 // the smaller size, change as needed
        }
        // all words are shorter than the threshold
        return 160.0 // the default size, change as needed
    }
}

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

ИСПРАВЛЕНО: Xcode 13.3 / iOS 15.4

      Text("Amazement Awaits us at every corner")

    .font(.system(size: 460))   // << even such size (or any other big)
    .foregroundColor(.blue)
    .foregroundColor(.white)
    .lineLimit(4)
    .multilineTextAlignment(.leading)
    .minimumScaleFactor(0.01)

Хотя я не нашел логической причины для исправления, но, похоже, вам нужно настроить

        .lineLimit(3)

https:https://stackru.com/images/d1d91e39ff14643e641ba23242f603f65087e64e.jpg

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

Другие вопросы по тегам