iosswiftswiftui

Adjust views in HStack where one of the children has aspectRatio


I'm trying to align Left View in HStack so that it will occupy all available height preserving aspectRatio. The Right View should shrink/expand according to the width of Left View.

So far I have this:

struct EmptyView: View {
    private let text: String
    init(_ text: String) {
        self.text = text
    }
    var body: some View {
        Text(text)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

struct TestView: View {
    @State private var items: [String] = (1..<100).map { "item_\($0).mp4" }

    var body: some View {
        VStack(spacing: 0) {
            HStack {
                EmptyView("Left View")
                    .aspectRatio(16.0/9.0, contentMode: .fit)
                    .background(.yellow)
                EmptyView("Right View")
                    .background(.red)
            }
                .ignoresSafeArea(.all, edges: .leading)
                .background(.blue)
            HStack {
                Button(
                    "Start",
                    systemImage: "play.fill",
                    action: {}
                ).tint(.white)
                Spacer()
                Button("Action", action: {})
                    .tint(.white)
                Spacer()
                Text("Status")
                    .foregroundStyle(.white)
            }
            .padding(.top, 16)
            .background(Color.black.opacity(0.8))
        }
        .persistentSystemOverlays(.hidden)
    }
}

Which looks like this:

enter image description here]

I would like Yellow view to adjust its height so that Blue background disappear and Red View will adjust. When aspect ratio is 16/9 then Red View width should be smaller.


Solution

  • You can use the .layoutPriority(1) modifier on the left view, also HStack(spacing: 0) (default spacing is 16 if not specified) and magic will happen.

    HStack(spacing: 0) {
        EmptyView("Left View")
            .aspectRatio(16.0/9.0, contentMode: .fit)
            .background(.yellow)
            .layoutPriority(1)
        EmptyView("Right View")
            .background(.red)
    }