SwiftUI:分段控制滚动

SwiftUI: Segmented Control scrolling

我正在使用分段控件在选项卡之间导航。 我的问题是,当我在一个选项卡内滚动时,所有其他选项卡也在漫步。这是我不想要的。

我希望滚动仅在所选选项卡内有效,当我单击其他选项卡时,它显示所选选项卡内容的顶部。

查看附加视频:https://imgur.com/a/Oxka4hv

这是我的代码

谢谢!

import SwiftUI

struct ContentView: View {
    
    @State var selectedState = 0
    @State var showTopTabBar: Bool = false
    
    var body: some View {
        
        ZStack (alignment: . top){
            
            ScrollView (showsIndicators: false){
                
                Text("Welcome")
                    .frame(height: 300)
                
                Picker("Options", selection: $selectedState) {
                    Text("First").tag(0)
                    Text("Second").tag(1)
                    Text("Third").tag(2)
                }
                .pickerStyle(SegmentedPickerStyle())
                .background(Color.white)
                .opacity(showTopTabBar ? 0 : 1)
                .readPos { rect in
                    if showTopTabBar != (rect.minY <= 100) {
                        showTopTabBar.toggle()
                    }
                }
                
                if (selectedState==0) {
                    
                    FirstView()
                    
                }
                
                else if (selectedState==1){
                    Secondview()
                }
                
                else {
                    ThirdView()
                }
                
                Spacer()
                
            }
            .padding()
            
            Picker("Options", selection: $selectedState) {
                Text("First").tag(0)
                Text("Second").tag(1)
                Text("Third").tag(2)
            }
            .pickerStyle(SegmentedPickerStyle())
            .padding()
            .background(Color.white)
            .opacity(showTopTabBar ? 1 : 0)
            
        }
    }
}


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


extension View {
    
    func readPos(onChange: @escaping (CGRect) -> Void) -> some View {
        background(
            GeometryReader { geometryProxy in
                Color.clear
                    .preference(key: CoordinatesPreferenceKey.self, value: geometryProxy.frame(in: .global))
            }
        )
            .onPreferenceChange(CoordinatesPreferenceKey.self, perform: onChange)
    }
    
}


private struct CoordinatesPreferenceKey: PreferenceKey {
    static var defaultValue: CGRect = .zero
    static func reduce(value: inout CGRect, nextValue: () -> CGRect) {}
}

您可以使用 ScrollViewReader 向上滚动以开始更改选项卡:

struct ContentView: View {
    
    @State var selectedState = 0
    @State var showTopTabBar: Bool = false
    
    var body: some View {
        
        ZStack (alignment: . top) {
            
            ScrollView (showsIndicators: false) {
                
                // added ScrollViewReader
                ScrollViewReader { scrollProxy in
                    
                    Text("Welcome")
                        .frame(height: 300)
                        .id("welcome")  // added id to scroll to
                    
                    tabPicker
                        .background(Color.white)
                        .opacity(showTopTabBar ? 0 : 1)
                        .readPos { rect in
                            if showTopTabBar != (rect.minY <= 100) {
                                showTopTabBar.toggle()
                            }
                        }
                    
                    if (selectedState==0) {
                        ListContentView(tab: "First View", color: .blue)
                    }
                    
                    else if (selectedState==1){
                        ListContentView(tab: "Second View", color: .green)
                    }
                    
                    else {
                        ListContentView(tab: "Third View", color: .orange)
                    }
                    Spacer()
                    
                    // on Change of selected Tab scroll to top
                        .onChange(of: selectedState) { newValue in
                            scrollProxy.scrollTo("welcome", anchor: .center)
                        }
                }
            }
            .padding()
            
            tabPicker
                .padding()
                .background(Color.white)
                .opacity(showTopTabBar ? 1 : 0)
        }
    }
    
    var tabPicker: some View {
        Picker("Options", selection: $selectedState) {
            Text("First").tag(0)
            Text("Second").tag(1)
            Text("Third").tag(2)
        }
        .pickerStyle(SegmentedPickerStyle())
    }
}


// dummy content view
struct ListContentView: View {
    
    let tab: String
    let color: Color
    
    var body: some View {
        ForEach(0..<30) { item in
            Text("\(tab) - \(item)")
                .padding()
                .frame(maxWidth: .infinity)
                .background(color)
        }
    }
}

这现在总是在切换 Tab 时向上滚动。如果您想保留每个选项卡中的位置,您必须根据显示内容的 .id 将它们保存在@State 变量中。