在 swiftUI 的 scrollView 中填充高度
Fill height in scrollView in swiftUI
我正在使用 swiftUI 进行编码,我有一个垂直的 scrollView
(见屏幕截图),在 scrollView
里面我有另一个水平的 scrollView
,在它下面我有一个 VStack
我希望高度填充屏幕的其余部分到垂直底部 scrollView
,但我似乎无法让它工作。
在某些情况下,垂直scrollView
中的内容可能比实际剩余的space大,这就是为什么我需要一个scrollView,但在其他一些情况下,内容比剩余的小space
这是我的代码:
VStack {
HeaderView
ScrollView(.vertical, showsIndicators: false) {
FriendsHorizontalScrollView()
VStack {
// I want this view to take all the remaining height left in the scrollView
FullHeightView()
}
.frame(width: UIScreen.main.bounds.width)
}
}
我最终得到的是这样的:
我想要的:
我尝试了几种解决方案,例如使用 geometryReader 或将 .frame(maxHeight: .infinity)
放在 VStack
上,但似乎没有任何效果。
这是一个基于视图偏好的可能方法的演示(ViewHeightKey
取自我的 解决方案。使用 Xcode 12 / iOS 14 进行了测试。
struct DemoLayoutInScrollView: View {
@State private var height1: CGFloat = .zero
@State private var height2: CGFloat = .zero
var body: some View {
VStack(spacing: 0) {
HeaderView()
GeometryReader { gp in
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 0) {
FriendsHorizontalScrollView()
.background(GeometryReader {
Color.clear
.preference(key: ViewHeightKey.self, value: [=10=].frame(in: .local).size.height)
})
.onPreferenceChange(ViewHeightKey.self) { self.height1 = [=10=] }
VStack(spacing: 0) {
// I want this view to take all the remaining height left in the scrollView
FullHeightView()
.background(GeometryReader {
Color.clear
.preference(key: ViewHeightKey.self, value: [=10=].frame(in: .local).size.height)
})
}.frame(height: max(gp.size.height - self.height1, self.height2))
.background(Color.yellow)
}
}
.onPreferenceChange(ViewHeightKey.self) { self.height2 = [=10=] }
}
}.frame(maxWidth: .infinity)
}
}
复制助手视图(用于测试)
struct FriendsHorizontalScrollView: View {
var body: some View {
Text("Horizontal Scroller")
.frame(maxWidth: .infinity)
.frame(height: 100)
.background(Color.green)
}
}
struct FullHeightView: View {
var body: some View {
ZStack {
Color.red
Text("Dynamic Content")
}
.frame(maxWidth: .infinity)
.frame(height: 300)
}
}
struct HeaderView: View {
var body: some View {
Rectangle().foregroundColor(.blue)
.frame(height: 60)
.overlay(Text("Header"))
}
}
这可以通过使用 GeometryReader
来实现。这个想法是设置根视图的minHeight
:
import SwiftUI
struct ContentView: View {
var body: some View {
GeometryReader { proxy in
ScrollView {
VStack(spacing: 0) {
Text("View 1")
.frame(height: 100)
.frame(maxWidth: .infinity)
.background(Color.green)
Text("View 2")
.frame(height: 100)
.frame(maxWidth: .infinity)
.background(Color.gray)
VStack {
Text("VStack")
Text("View 3")
.frame(height: 100)
.frame(maxWidth: .infinity)
.background(Color.blue)
.padding()
}
.frame(maxHeight: .infinity)
.background(Color.yellow)
}
.frame(minHeight: proxy.size.height)
}
}
.edgesIgnoringSafeArea(.all)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
我正在使用 swiftUI 进行编码,我有一个垂直的 scrollView
(见屏幕截图),在 scrollView
里面我有另一个水平的 scrollView
,在它下面我有一个 VStack
我希望高度填充屏幕的其余部分到垂直底部 scrollView
,但我似乎无法让它工作。
在某些情况下,垂直scrollView
中的内容可能比实际剩余的space大,这就是为什么我需要一个scrollView,但在其他一些情况下,内容比剩余的小space
这是我的代码:
VStack {
HeaderView
ScrollView(.vertical, showsIndicators: false) {
FriendsHorizontalScrollView()
VStack {
// I want this view to take all the remaining height left in the scrollView
FullHeightView()
}
.frame(width: UIScreen.main.bounds.width)
}
}
我最终得到的是这样的:
我想要的:
我尝试了几种解决方案,例如使用 geometryReader 或将 .frame(maxHeight: .infinity)
放在 VStack
上,但似乎没有任何效果。
这是一个基于视图偏好的可能方法的演示(ViewHeightKey
取自我的
struct DemoLayoutInScrollView: View {
@State private var height1: CGFloat = .zero
@State private var height2: CGFloat = .zero
var body: some View {
VStack(spacing: 0) {
HeaderView()
GeometryReader { gp in
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 0) {
FriendsHorizontalScrollView()
.background(GeometryReader {
Color.clear
.preference(key: ViewHeightKey.self, value: [=10=].frame(in: .local).size.height)
})
.onPreferenceChange(ViewHeightKey.self) { self.height1 = [=10=] }
VStack(spacing: 0) {
// I want this view to take all the remaining height left in the scrollView
FullHeightView()
.background(GeometryReader {
Color.clear
.preference(key: ViewHeightKey.self, value: [=10=].frame(in: .local).size.height)
})
}.frame(height: max(gp.size.height - self.height1, self.height2))
.background(Color.yellow)
}
}
.onPreferenceChange(ViewHeightKey.self) { self.height2 = [=10=] }
}
}.frame(maxWidth: .infinity)
}
}
复制助手视图(用于测试)
struct FriendsHorizontalScrollView: View {
var body: some View {
Text("Horizontal Scroller")
.frame(maxWidth: .infinity)
.frame(height: 100)
.background(Color.green)
}
}
struct FullHeightView: View {
var body: some View {
ZStack {
Color.red
Text("Dynamic Content")
}
.frame(maxWidth: .infinity)
.frame(height: 300)
}
}
struct HeaderView: View {
var body: some View {
Rectangle().foregroundColor(.blue)
.frame(height: 60)
.overlay(Text("Header"))
}
}
这可以通过使用 GeometryReader
来实现。这个想法是设置根视图的minHeight
:
import SwiftUI
struct ContentView: View {
var body: some View {
GeometryReader { proxy in
ScrollView {
VStack(spacing: 0) {
Text("View 1")
.frame(height: 100)
.frame(maxWidth: .infinity)
.background(Color.green)
Text("View 2")
.frame(height: 100)
.frame(maxWidth: .infinity)
.background(Color.gray)
VStack {
Text("VStack")
Text("View 3")
.frame(height: 100)
.frame(maxWidth: .infinity)
.background(Color.blue)
.padding()
}
.frame(maxHeight: .infinity)
.background(Color.yellow)
}
.frame(minHeight: proxy.size.height)
}
}
.edgesIgnoringSafeArea(.all)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}