Как ограничить размер GeometryReader внутри VStack - PullRequest
0 голосов
/ 06 мая 2020

Я хотел бы, чтобы GeometryReader не вмешивался в мой макет в VStack, но я не уверен, какой подход правильный.

Учитывая пример простого графика с заголовком и caption:

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

Дает ожидаемый результат:

enter image description here

Но если мы обновим представление Graph, чтобы использовать GeometryReader, чтобы равномерно разделить график по ширине экрана, при изменении макета.

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

enter image description here

Есть ли способ разрешить обзору Graph просто заполнить его естественную высоту и не использовать всю доступную высоту при использовании GeometryReader.

Имейте в виду, что Graph может быть любым представлением здесь, где точный размер неизвестен, поэтому установка статического c размера невозможна. т.е. без GeometryReader, Graph может занимать только необходимое количество вертикального пространства в VStack.

1 Ответ

0 голосов
/ 06 мая 2020

Вот возможное решение. Протестировано с Xcode 11.4 / iOS 13.4

enter image description here

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