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



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

  • 1">
  • 1英寸
  • 1英寸
  • 一英寸

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

  • truncationMode(_:):只接受位置参数,没有自定义截断选项
  • GeometryReader:告诉我有什么空间可用(非常有用!(,但我不知道如何动态选择动态大小的子视图,似乎是为了生成固定大小的子视图或溢出位置而优化的

当我试图找到另一个可能解决了这个问题的应用程序时,它们似乎都根据方向或其他大小的变化重新排列了布局。我希望继续使用适合空间的Text视图中的单个HStack,尽可能避免截断所有重要信息。

让我们定义这个视图:

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

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

最新更新