[英]SwiftUI TabView with PageTabViewStyle dynamic height based on Content
如何使带有TabView
的PageTabViewStyle
将其高度调整为内容的高度?
我有一个SwiftUI
视图,如下所示:
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)
}
}
这会产生如下所示的 output:
可以看到, TabView
的内容被截断了。 我知道,我可以删除.fixedSize
,但视图看起来像这样:
我希望 TabView 响应内容的高度。 关于如何实现这一目标的任何想法?
一种可能的方法是在运行时动态获取内容 rect 并通过视图首选项传输给父级,因此父级可以将其设置为适合内容的框架。
用 Xcode 13.3 / iOS 15.4 测试
这是主要部分:
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
}
我从 Asperi 的回答中获得了灵感,但是我必须修改一些东西才能使其适用于我的情况。
在 TabView 的“内容”中,我添加了这些:
.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
}
}
其中 viewPagerSize 最初是:
@State var viewPagerSize: CGSize = .zero
我的 PreferenceKey 看起来像这样:
struct ViewRectKey: PreferenceKey {
static let defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
value = nextValue()
}
}
总的来说,代码如下所示:
@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()
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.