将索引视图移至选项卡视图中的主页指示器上方

Osc*_*and 6 ios swift swiftui

我遇到了 SwiftUI 的一个恼人的问题。我有一个水平寻呼机,其垂直滚动视图为页面。它的定义很简单,

TabView(selection: $selected) {
    ForEach(focus!.list.things) { thing in
        FullView(thing: thing).tag(thing)
    }
}
.tabViewStyle(.page(indexDisplayMode: .always))
.indexViewStyle(.page(backgroundDisplayMode: .always))
Run Code Online (Sandbox Code Playgroud)

struct FullView: View {
    let thing: Thing
    
    var body: some View {
        ScrollView {
            VStack {
                ...
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这会产生一个符合我要求的视图,只是它没有一直到达主页指示器下方。

我可以通过添加.ignoresSafeArea(edges: .bottom)到 来解决这个问题TabView,但这会产生另一个令人不快的结果,页面指示器与主页指示器发生冲突。


是否有任何合理的方法可以实现全高度垂直滚动,同时将索引页指示器保持在主页指示器上方?

重现问题的代码:

struct ContentView: View {
    @State var isSheetUp = false
    
    var body: some View {
        Button("Present") {
            isSheetUp.toggle()
        }
        .sheet(isPresented: $isSheetUp) {
            Sheet()
        }
    }
    
    struct Sheet: View {
        var body: some View {
            NavigationView {
                TabView() {
                    Page()
                    Page()
                    Page()
                }
                // Comment this to switch layout issue
                .ignoresSafeArea(edges: .bottom)
                .tabViewStyle(.page(indexDisplayMode: .always))
                .indexViewStyle(.page(backgroundDisplayMode: .always))
                .navigationTitle("Title")
                .navigationBarTitleDisplayMode(.inline)
            }
        }
    }
    
    struct Page: View {
        var body: some View {
            ScrollView {
                VStack {
                    Rectangle()
                        .foregroundColor(.teal)
                        .padding()
                        .frame(minHeight: 10000)
                }
            }.background(Color.brown)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Run Code Online (Sandbox Code Playgroud)

Cod*_*256 5

编辑:另请参阅@nekno 的精彩补充


如果您创建自定义UIPageControl,手动标记 中的每个选项卡TabView,并确保跟踪numberOfPages

struct PageControlView: UIViewRepresentable {
    @Binding var currentPage: Int
    @Binding var numberOfPages: Int

    func makeUIView(context: Context) -> UIPageControl {
        let uiView = UIPageControl()
        uiView.backgroundStyle = .prominent
        uiView.currentPage = currentPage
        uiView.numberOfPages = numberOfPages
        return uiView
    }

    func updateUIView(_ uiView: UIPageControl, context: Context) {
        uiView.currentPage = currentPage
        uiView.numberOfPages = numberOfPages
    }
}

struct ContentView: View {
    @State var isSheetUp = false

    var body: some View {
        Button("Present") {
            isSheetUp.toggle()
        }
        .sheet(isPresented: $isSheetUp) {
            Sheet()
        }
    }

    struct Sheet: View {
        @State var currentPage = 0
        @State var numberOfPages = 3

        var body: some View {
            NavigationView {
                ZStack {
                    TabView(selection: $currentPage) {
                        Page().tag(0)
                        Page().tag(1)
                        Page().tag(2)
                    }
                    // Comment this to switch layout issue
                    .ignoresSafeArea(edges: .bottom)
                    .tabViewStyle(.page(indexDisplayMode: .never))
                    .indexViewStyle(.page(backgroundDisplayMode: .always))
                    .navigationTitle("Title")
                    .navigationBarTitleDisplayMode(.inline)

                    VStack {
                        Spacer()
                        PageControlView(currentPage: $currentPage, numberOfPages: $numberOfPages)
                    }
                }
            }
        }
    }

    struct Page: View {
        var body: some View {
            ScrollView {
                VStack {
                    Rectangle()
                        .foregroundColor(.teal)
                        .padding()
                        .frame(minHeight: 10000)
                }
            }.background(Color.brown)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Run Code Online (Sandbox Code Playgroud)