当嵌入到 SwiftUI 中的 ScrollView 中时,VStack 内的内容会缩小

Posted

技术标签:

【中文标题】当嵌入到 SwiftUI 中的 ScrollView 中时,VStack 内的内容会缩小【英文标题】:Content inside VStack shrinks when embedded inside a ScrollView in SwiftUI 【发布时间】:2021-02-19 12:27:03 【问题描述】:

我有一个带有两个文本字段和一个按钮的简单登录屏幕。它应该看起来像这样。两个文本字段靠得更近,按钮往下一点。

这是我的代码。

struct ContentView: View 
    var body: some View 
        VStack 
            Spacer()
            InputTextField(title: "First Name", text: .constant(""))
            InputTextField(title: "Last Name", text: .constant(""))
            Spacer()
            ActionButton(title: "Login", action: )
            Spacer()
        
    



struct InputTextField: View 
    let title: String
    
    @Binding var text: String
    
    var body: some View 
        VStack(alignment: .leading) 
            Text(title)
                .foregroundColor(.primary)
                .fontWeight(.medium)
                .font(.system(size: 18))
            
            HStack 
                TextField("", text: $text)
                    .frame(height: 54)
                    .textFieldStyle(PlainTextFieldStyle())
                    .cornerRadius(10)
            
            .padding([.leading, .trailing], 10)
            .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 0.6))
        
        .padding()
    



struct ActionButton: View 
    let title: String
    var action: () -> Void

    var body: some View 
        Button(title) 
            action()
        
        .frame(minWidth: 100, idealWidth: 100, maxWidth: .infinity, minHeight: 60, idealHeight: 60)
        .font(.system(size: 24, weight: .bold))
        .foregroundColor(.white)
        .background(Color.blue)
        .cornerRadius(10)
        .padding([.leading, .trailing])
        .shadow(color: Color.gray, radius: 2, x: 0, y: 2)
    

我想将它嵌入到 ScrollView 中,以便用户可以在键盘出现时上下滚动。

struct ContentView: View 
    var body: some View 
        ScrollView 
            VStack 
                Spacer()
                InputTextField(title: "First Name", text: .constant(""))
                InputTextField(title: "Last Name", text: .constant(""))
                Spacer()
                ActionButton(title: "Login", action: )
                Spacer()
            
        
    

这是我遇到此问题的地方。当我在ScrollView 中添加VStack 时,所有内容都会缩小并显示聚集在一起。似乎 Spacers 在 ScrollView 内时无效。

我该如何解决这个问题?

Demo project

【问题讨论】:

【参考方案1】:

在这里,您需要通过如下给出最小高度来使内容拉伸以填充整个滚动视图

struct ContentView: View 
  var body: some View 
    GeometryReader  gr in
        ScrollView 
            VStack 
                Spacer()
                InputTextField(title: "First Name", text: .constant(""))
                InputTextField(title: "Last Name", text: .constant(""))
                Spacer()
                ActionButton(title: "Login", action: )
                Spacer()
            
            .frame(minHeight: gr.size.height)
        
    
  

这是输出:

【讨论】:

很好的解决方案。我一直在寻找这样的东西一个多小时。现在我可以安然入睡了。【参考方案2】:

正如您所发现的,当它们在 ScrollView 中或不在 ScrollView 中时,Spacers 的行为会有所不同,或者当它们可以展开的轴是无限的或有限的时,它们的行为会有所不同。

如果您希望内容在适合时垂直居中并在大于屏幕时滚动,我会这样做:

struct ContentView: View 
    var body: some View 
        VStack  // This new stack would vertically center the content
                 // (I haven't actually tried it though)
            ScrollView 
                VStack 
                    Spacer().size(height: MARGIN) // The minimum margin you want
                    InputTextField(title: "First Name", text: .constant(""))
                    InputTextField(title: "Last Name", text: .constant(""))
                    Spacer().size(height: SPACING)
                    ActionButton(title: "Login", action: )
                    Spacer().size(height: MARGIN)
                
            
        
    

【讨论】:

以上是关于当嵌入到 SwiftUI 中的 ScrollView 中时,VStack 内的内容会缩小的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:当 List 和 ForEach 嵌入 TabView 时 WatchOS 8.1 中的 NavigationView 错误

从 swiftUI 中的一个嵌入式 UIViewController 导航到 swift UI 中的另一个嵌入式 UIViewcontroller

在 SwiftUI 中的 tabview 中嵌入 webview

为啥嵌入到 SwiftUI 表单中的按钮不起作用?

SwiftUI嵌入在Form或Section中的视图上下文菜单(contextMenu)无法独立弹出的解决

使用 XCUIElementQuery 在 SwiftUI 中查找嵌入在表单中的 DatePicker() 的可访问性(标识符:)