Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI TabView with PageTabViewStyle dynamic height based on Content

How do I make my SwiftUI TabView with a PageTabViewStyle adjust its height to the height of the content?

I have a SwiftUI view like follows:

struct TabViewDynamicHeight: View {
    var body: some View {
        VStack {
            TabView {
                ForEach(0..<5, id: \.self) { index in
                    VStack {
                        Text("Text \(index)")
                        Text("Text \(index)")
                        Text("Text \(index)")
                    }
                }
            }
            .tabViewStyle(PageTabViewStyle())
            .background(Color.red)
            .fixedSize(horizontal: false, vertical: true)
        }
        .background(Color.blue)
    }
}

This produces an output like this:

enter image description here

You can see, that the content of the TabView is cut off. I'm aware, that I can remove .fixedSize, but than the view looks like this:

enter image description here

I would like the TabView to respond to the height of the content. Any ideas on how to achieve that?

like image 405
Esera Avatar asked Nov 15 '22 21:11

Esera


1 Answers

A possible approach is to fetch content rect dynamically in run-time and transfer to parent via view prefs, so parent can set it as frame to fit content.

Tested with Xcode 13.3 / iOS 15.4

demo

Here is main part:

VStack {
    Text("Text \(index)")
    Text("Text \(index)")
    Text("Text \(index)")
}
.frame(maxWidth: .infinity)
.background(GeometryReader {
    Color.clear.preference(key: ViewRectKey.self,
                                  value: [$0.frame(in: .local)])
})

// ...

.frame(height: rect.size.height
         + 60 /* just to avoid page indicator overlap */)
.onPreferenceChange(ViewRectKey.self) { rects in
    self.rect = rects.first ?? .zero
}

Complete test code in project is here

like image 66
Asperi Avatar answered Jan 03 '23 09:01

Asperi