Как выбрать текстовое представление SwiftUI или строку в зависимости от доступного пространства? - PullRequest
1 голос
/ 27 марта 2020

Например, если мой пользовательский интерфейс должен отображать длину Measurement в удобочитаемой форме, он может выбрать один из следующих форматов для отображения на один дюйм:

  • 1 "
  • 1 дюйм
  • 1 дюйм
  • один дюйм

До сих пор я пробовал:

  • truncationMode(_:) : принимает только позиционный аргумент, нет опции для пользовательского усечения
  • GeometryReader: говорит мне, какое место доступно (супер полезно!), но я не вижу, как динамически выбирать подвид динамического размера, кажется оптимизироваться для генерации вложенных видов фиксированного размера или переполнения позиции

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

1 Ответ

1 голос
/ 27 марта 2020

Давайте определим это представление:

struct FlexibleTextView: View {
    let possibleTexts: [String]

    var body: some View {
        GeometryReader { geometry in
            Text(self.possibleTexts.last(where: { $0.size(withAttributes: [.font: UIFont.systemFont(ofSize: 17.0)]).width < geometry.size.width }) ?? self.possibleTexts[0])
                .lineLimit(1)
        }
    }

    init(_ possibleTexts: [String]) {
        self.possibleTexts = possibleTexts.sorted {
            $0.size(withAttributes: [.font: UIFont.systemFont(ofSize: 17.0)]).width < $1.size(withAttributes: [.font: UIFont.systemFont(ofSize: 17.0)]).width
        }
    }
}

Когда вы его инициализируете, возможные тексты автоматически сортируются по их фактической ширине. Он берет последний (то есть один ширина наибольшую ширину), где ширина меньше ширины контейнера, которую мы получаем из GeometryReader. Если даже первый, то есть самый маленький текст слишком большой (поэтому .last(where: { ... }) вернет ноль), мы по-прежнему будем использовать этот первый текст, но вы также можете изменить его самостоятельно на то, что захотите.

Вот интерактивный пример:

struct ContentView: View {
    @State var width: CGFloat = 80

    var body: some View {
        VStack {
            FlexibleTextView(["1\"", "1 in", "1 inch", "one inch"])
                .frame(width: width, height: 17)
                .border(Color.red)

            Slider(value: $width, in: 10 ... 80)
        }
        .padding()
    }
}

С помощью ползунка вы можете настроить ширину, чтобы увидеть эффект.

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