using SwiftUI, when scrolling, VStack inside Section shrinks and expands

298 Views Asked by At

I'm trying to make simple testing app with Buttons and Options for Button action.

target is iOS 13.0 for backward compatibility.

expected smooth scroll just like other iOS app does, but it stutters. some VStack is continuously shrink and expand, keep changing scrolls height so it stutters I think.

here's video: https://i.stack.imgur.com/7IEfo.jpg

if I stop just right at stutter-bottom point, there's shrunken VStack.

you can see that shrunken VStack at end of video.

here's the code of main View. (shrunken Section is SectionH.)

import SwiftUI

struct ContentView: View {
    @Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
    @Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
    
    var body: some View {
        if(verticalSizeClass == .regular && horizontalSizeClass == .compact) {
            VStack {
                List {
                    SectionA()
                    SectionB()
                    SectionC()
                    SectionD()
                    SectionE()
                    SectionF()
                    SectionG()
                    SectionH()
                }
                
                OtherView()
            }
        } else {
            HStack {
                List {
                    SectionA()
                    SectionB()
                    SectionC()
                    SectionD()
                    SectionE()
                    SectionF()
                    SectionG()
                    SectionH()
                }
                
                OtherView()
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

and heres simple examples of other Sections(A to G are similar.)

import SwiftUI

struct SectionF: View {
    @State var bool1 : Bool = true;
    
    @State var text1: String = "text"
    @State var text2: String = "text"
    @State var text3: String = "text"
    @State var text4: String = "text"
    
    
    var body: some View {
        Section(header: Text("Section F")) {
            Button{
            } label: {
                Text("button")
            }
            
            VStack(alignment: .leading) {
                Button{
                } label: {
                    Text("button: \(bool1 ? "true" : "false")")
                }
                Toggle("bool", isOn: $bool1)
            }
            
            
            VStack(alignment: .leading) {
                Button{
                } label: {
                    Text("button")
                }
                HStack {
                    Text("text: ")
                    TextField("text", text: $text1)
                }
                HStack {
                    Text("text: ")
                    TextField("text", text: $text2)
                }
                HStack {
                    Text("text: ")
                    TextField("text", text: $text3)
                }
                HStack {
                    Text("text: ")
                    TextField("text", text: $text4)
                }
            }
            
            VStack(alignment: .leading) {
                Button{
                } label: {
                    Text("button")
                }
                HStack {
                    Text("text: ")
                    TextField("text", text: $text1)
                }
            }
        }
    }
}

struct SectionF_Previews: PreviewProvider {
    static var previews: some View {
        Form {
            SectionF()
        }
        
    }
}

and here's dreaded Section H.

import SwiftUI

struct SectionH: View {
    @State var text1: String = "text"
    @State var text2: String = "text"
    @State var picker1: String = "1"
    var picker1s = ["1", "2"]
    @State var text3: String = "text"
    @State var text4: String = "text"
    
    
    @State var bool1 : Bool = true;
    @State var text5: String = "text"
    @State var bool2 : Bool = true;
    @State var bool3 : Bool = true;
    @State var number1: String = "0"
    
    
    var body: some View {
        Section(header: Text("Section H")) {
            VStack(alignment: .leading) {
                Button{
                } label: {
                    Text("button")
                }
                
                HStack {
                    Text("text: ")
                    TextField("text", text: $text1)
                }
                
                HStack {
                    Text("text: ")
                    TextField("text", text: $text2)
                }
                VStack(alignment: .leading) {
                    Text("picker: \(picker1)")
                    Picker("picker", selection: $picker1) {
                        ForEach(picker1s, id: \.self) {
                          Text($0)
                        }
                    }.pickerStyle(.segmented)
                }
                
                HStack {
                    Text("text: ")
                    TextField("text", text: $text3)
                }
                
                HStack {
                    Text("text: ")
                    TextField("text", text: $text4)
                }
            }
        
        
            Button {
            } label: {
                Text("Button")
            }
            
            VStack(alignment: .leading) {
                Button {
                } label: {
                    Text("Button")
                }
                VStack {
                    
                    HStack {
                        Text("text: ")
                        TextField("text", text: $text1)
                    }
                    HStack {
                        Text("text: ")
                        TextField("text", text: $text2)
                    }
                    VStack(alignment: .leading) {
                        Text("picker: \(picker1)")
                        Picker("picker", selection: $picker1) {
                            ForEach(picker1s, id: \.self) {
                              Text($0)
                            }
                        }.pickerStyle(.segmented)
                    }
                }
                
                //**this is shrinking VStack!**
                VStack {
                    Toggle("bool", isOn: $bool1)
                    
                    HStack {
                        Text("text: ")
                        TextField("text", text: $text3)
                    }
                    
                    HStack {
                        Text("text: ")
                        TextField("text", text: $text5)
                    }
                    
                    Toggle("bool", isOn: $bool2)
                    
                    Toggle("bool", isOn: $bool3)
                    
                    HStack {
                        Text("number: ")
                        TextField("number", text: $number1)
                    }
                }
                
            }
        }
    }
}

struct SectionH_Previews: PreviewProvider {
    static var previews: some View {
        Form {
            SectionH()
        }
    }
}

here's what I tried:

  • changing List to Form
  • changing Sections order
  • removing V/HStack changing by orientation <- this one removes stutter!
  • reducing options from SectionH
  • divide SectionHs options into 2 VStack <- is applied to code above.

I'm new to Swift and SwiftUI, I don't know why this happens and can't get any clues to solve this problem.

thanks in advice.

UPDATE

removed SectionH, not fixed.

removed OtherView, not fixed.

I think theres a clue on if state with orientation.

0

There are 0 best solutions below