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:
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:
I would like the TabView to respond to the height of the content. Any ideas on how to achieve that?
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
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
}
I took inspiration from Asperi' answer, however I had to modify some things to make it work in my case.
On the 'Content' of the TabView, I added these:
.overlay(GeometryReader { proxy in
Color.clear.preference(key: ViewRectKey.self, value: proxy.size)
})
.onPreferenceChange(ViewRectKey.self) { size in
if self.viewPagerSize.height == .zero {
self.viewPagerSize = size
}
}
Where viewPagerSize is initially:
@State var viewPagerSize: CGSize = .zero
My PreferenceKey looks like this:
struct ViewRectKey: PreferenceKey {
static let defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
value = nextValue()
}
}
In total the code looks like this:
@ViewBuilder
func createViewPager() -> some View {
TabView {
ForEach(views(), id: \.id) { _ in
createInformationSquareView()
.background(Color(.systemGray6))
.overlay(GeometryReader { proxy in
Color.clear.preference(key: ViewRectKey.self, value: proxy.size)
})
.onPreferenceChange(ViewRectKey.self) { size in
if self.viewPagerSize.height == .zero {
self.viewPagerSize = size
}
}
}
}
.cornerRadius(10)
.frame(height: self.viewPagerSize.height + 60)
.tabViewStyle(.page)
.indexViewStyle(.page(backgroundDisplayMode: .always))
.padding()
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.