首页 > 解决方案 > 如何限制 VStack 中 GeometryReader 的大小

问题描述

我想停止GeometryReader干扰我的布局,VStack但我不确定正确的方法是什么。

给定一个带有标题和标题的简单图形示例:

struct Graph: View {
  var body: some View {
    HStack(spacing: 0) {
      Color.red.frame(width: 100, height: 80)
      Color.blue.frame(width: 100, height: 120)
      Color.green.frame(width: 100, height: 180)
    }
  }
}

struct GraphExample: View {
  var body: some View {
    VStack {

      Text("My graph")

      // Graph represents a custom view with a natural and non-static height
      Graph()

      Text("My graph caption")
    }
  }
}

产生这个预期的结果:

在此处输入图像描述

但是,如果我们更新Graph视图以使用 aGeometryReader在屏幕宽度上均匀分割图形,则布局会发生变化。

struct Graph: View {
  var body: some View {
    GeometryReader { proxy in
      HStack(spacing: 0) {
        Color.red.frame(width: proxy.size.width / 3, height: 80)
        Color.blue.frame(width: proxy.size.width / 3, height: 120)
        Color.green.frame(width: proxy.size.width / 3, height: 180)
      }
    }
  }
}

这使得Graph视图填充了所有可用空间VStack

在此处输入图像描述

有没有办法让Graph视图只填充其自然高度,并且在仍然使用GeometryReader.

请记住,Graph此处可能是任何不知道确切大小的视图,因此无法设置静态大小。即没有GeometryReader, Graphcan 只占用 VStack 中所需的垂直空间量。

标签: swiftuivstackgeometryreader

解决方案


这是可能的解决方案。使用 Xcode 11.4 / iOS 13.4 测试

在此处输入图像描述

struct Graph: View {
  @State private var width = UIScreen.main.bounds.width // just initial constant
  var body: some View {
      HStack(spacing: 0) {
        Color.red.frame(width: width / 3, height: 80)
        Color.blue.frame(width: width / 3, height: 120)
        Color.green.frame(width: width / 3, height: 180)
      }.background(GeometryReader { gp -> Color in
        let frame = gp.frame(in: .local)
        DispatchQueue.main.async {
            self.width = frame.size.width // << dynamic, on layout !!
        }
        return Color.clear
      })
  }
}

推荐阅读