如何根据可用空间选择SwiftUI文本视图或字符串?

时间:2020-03-27 02:11:59

标签: swiftui

例如,如果我的UI需要以人类可读的形式显示长度Measurement,则它可能要从以下一种格式中选择以显示一英寸:

  • 1“
  • 1英寸
  • 1英寸
  • 一英寸

到目前为止,我已经尝试过:

  • truncationMode(_:):仅接受位置参数,没有自定义截断选项
  • GeometryReader:告诉我什么空间可用(超级有用!),但我看不到如何动态选择动态大小的子视图,似乎已针对生成固定大小的子视图或溢出进行了优化职位

当我尝试找到另一个可能已解决此问题的应用程序时,似乎它们都根据方向或其他尺寸变化重新排列了布局。我希望继续在HStack个视图中保留一个Text个适合该空间的视图,以防止所有重要信息在可能的情况下被截断。

1 个答案:

答案 0 :(得分:1)

让我们定义这个视图:

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: { ... })将返回nil),我们仍将使用该第一个文本,但是您也可以自己更改为所需的文本。

这是一个交互式示例:

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()
    }
}

使用滑块,您可以调节宽度以查看效果。