0

I want to achieve this (For the screenshots I used constant heights, just to visualize what I am looking for):

Goal (1) Goal (1)

The two Views containing text should together have the same height as the (blue) Image View. The right and left side should also be of the same width. The important part: The Image View can have different aspect ratios, so I can't set a fixed height for the parent View. I tried to use a GeometryReader, but without success, because when I use geometry.size.height as height, it takes up the whole screen height.

This is my code:

import SwiftUI

struct TestScreen: View {
    var body: some View {
        VStack {
            GeometryReader { geometry in
                HStack {
                    Image("blue-test-image")
                        .resizable()
                        .scaledToFit()
                        .frame(maxWidth: .infinity)
                    VStack {
                        Text("Some Text")
                            .padding()
                            .frame(maxWidth: .infinity, maxHeight: .infinity)
                            .background(Color.gray)
                        Text("Other Text")
                            .padding()
                            .frame(maxWidth: .infinity, maxHeight: .infinity)
                            .background(Color.gray)
                    }
                    .frame(maxWidth: .infinity, maxHeight: geometry.size.height /* should instead be the height of the Image View */)
                }
            }
            Spacer()
        }
        .padding()
    }
}

This is a screenshot of what my code leads to: enter image description here

Any help would be appreciated, thanks!

Steffen
  • 129
  • 7
  • 2
    Does this answer your question https://stackoverflow.com/a/62451599/12299030? – Asperi Nov 12 '21 at 16:42
  • As I can see in your photos, you already fixed the issue, so what you looking for more? – ios coder Nov 12 '21 at 16:49
  • @swiftPunk for the photos I just used fixed heights to show what I want to achieve. – Steffen Nov 12 '21 at 17:09
  • @Asperi Thanks, that hasn't worked for me yet, because (I think) the Image doesn't fire a `onPreferenceChange` event. I would have to do it e.g. in `onAppear`, but I don't know how to access its height then. – Steffen Nov 12 '21 at 17:37
  • @Steffen: Your question is not clear! As I see in your code you did not used any hard coded value! And You already have what you want. So what is the point of your question? – ios coder Nov 12 '21 at 21:32
  • 1
    @Steffen if you are still having problems with the `PreferenceKeys` put up a new question with your code and we can help. – Yrb Nov 13 '21 at 18:19

1 Answers1

2

As @Asperi pointed out, this solves the problem: stackoverflow.com/a/62451599/12299030

This is how I solved it in this case:

import SwiftUI

struct TestScreen: View {
    @State private var imageHeight = CGFloat.zero

    var body: some View {
        VStack {
            HStack {
                Image("blue-test-image")
                    .resizable()
                    .scaledToFit()
                    .frame(maxWidth: .infinity)
                    .background(GeometryReader {
                        Color.clear.preference(
                            key: ViewHeightKeyTestScreen.self,
                            value: $0.frame(in: .local).size.height
                        )
                    })
                VStack {
                    Text("Some Text")
                        .padding()
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .background(Color.gray)
                    Text("Other Text")
                        .padding()
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .background(Color.gray)
                }
                .frame(maxWidth: .infinity, minHeight: self.imageHeight, maxHeight: self.imageHeight)
            }
            .onPreferenceChange(ViewHeightKeyTestScreen.self) {
                self.imageHeight = $0
            }
            Spacer()
        }
        .padding()
    }
}

struct ViewHeightKeyTestScreen: PreferenceKey {
    static var defaultValue: CGFloat { 0 }
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value += nextValue()
    }
}

struct TestScreen_Previews: PreviewProvider {
    static var previews: some View {
        TestScreen()
    }
}

Steffen
  • 129
  • 7