0

I'm trying to use SwiftUI to build something along the lines of a header/content/footer with a VStack. I'd like the header and footer to take up 10% each of the height of the screen, and the content to expand to fill up the rest. This pattern could be useful for things other than header/content/footer, so if there's already something that implements this pattern (middle view expanding, or something along those lines), that would be great...

This is probably super simple to experienced swift devs, but I can't seem to find an example of it anywhere.

Any advice/pointers/code would be greatly appreciated!

My existing, super-simple code, with all of my experiments removed:


import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack() {
            Header()
            Content()
            Footer()
        }
        .frame(minWidth: 0,
               maxWidth: .infinity,
               minHeight: 0,
               maxHeight: .infinity,
               alignment: Alignment.topLeading)
        .border(Color.red)

    }
}

struct Header: View {
    var body: some View {
        HStack() {
            Text("Header")
        }
        .padding()
        .border(Color.blue)
    }
}

struct Content: View {
    var body: some View {
        HStack() {
            Text("Content")
        }
        .padding()
        .border(Color.black)
    }
}

struct Footer: View {
    var body: some View {
        HStack() {
            Text("Footer")
        }
        .padding()
        .border(Color.green)
    }
}

1 Answer 1

1

I think you may use GeometryReader in your case:

struct HeaderContentFooter: View {

    var body: some View {

        GeometryReader { geometry in

            VStack(spacing: 0) {
                Rectangle() // header
                    .foregroundColor(.red)
                    .frame(height: geometry.size.height / 10)

                Rectangle() // content, which fill up everything with VStack

                Rectangle() // footer
                    .foregroundColor(.red)
                    .frame(height: geometry.size.height / 10)
            }

        }
        .edgesIgnoringSafeArea(.all)

    }
}

the result should be: enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

Hey, this is great, thanks! Is there something special about the Rectangle view that makes this work? If I change the Rectangle to Text (or HStack, or whatever), it no longer works. If you change the middle Rectangle to Text("Content"), it no longer fills up the space. Thanks again!
@Hoopes there are several solutions to achieve this: use the same technique: Text("hello").frame(height: geometry.size.height * 0.9) ; put everything in the middle into view, which takes up all the space by default (such as ScrollView, GeometryReader, etc.); put everything into ZStack and use the same Rectangle(). as example: ZStack { Rectangle().foregroundColor(.white) // you can google how to change color with colorScheme Text("hello!") }
@Hoopes answering your question: yes, Rectangle takes up all the space. By the way, I remembered another solution: put middle View into VStack and use Spacer() at the top and at the bottom (VStack { Spacer(); Text("1"); Spacer() })
Thanks again - fiddling with spacers enough got me far enough to where I'm headed. Still a little counterintuitive (especially order of things, like frame), but I guess that's how you learn.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.