如何在PageTabView中梳理相邻页面?

Pau*_*aul 11 ios tabview swift swiftui pagetabviewstyle

我正在使用 SwiftUI 2 并使用 TabView 和 PageTabViewStyle。

现在,我正在寻找一种方法来“逗弄”与当前页面相邻的页面,如下所示:

图片来源:http://ios-dev.co/swiftui/how-to-create-page-view-in-swiftui/

用TabView和PageTabViewStyle可以实现这种效果吗?

我已经尝试将 TabView 的宽度减小为windowWidth-50。然而,这并没有导致相邻页面在侧面可见。50px相反,此更改在右窗口边框左侧引入了硬垂直边缘,新页面将滑入其中。

Chr*_*isR 6

这是一个简单的实现。您可以将结构与 AnyView 数组一起使用,或直接在您自己的实现中使用逻辑。

在此输入图像描述

struct ContentView: View {
    
    @State private var selected = 4

    var body: some View {
        
        // the trailing closure takes an Array of AnyView type erased views
        TeasingTabView(selectedTab: $selected, spacing: 20) {
            [
                AnyView(TabContentView(title: "First", color: .yellow)),
                AnyView(TabContentView(title: "Second", color: .orange)),
                AnyView(TabContentView(title: "Fourth", color: .green)),
                AnyView(TabContentView(title: "Fifth", color: .blue)),
                AnyView(
                    Image(systemName: "lizard")
                        .resizable().scaledToFit()
                        .padding()
                        .frame(maxHeight: .infinity)
                        .border(.red)
                )
            ]
        }
    }
}
        
        
struct TeasingTabView: View {
    
    @Binding var selectedTab: Int
    let spacing: CGFloat
    let views: () -> [AnyView]
    
    @State private var offset = CGFloat.zero
    var viewCount: Int { views().count }

    var body: some View {
        
        VStack(spacing: spacing) {
            GeometryReader { geo in
                let width = geo.size.width * 0.7
                
                LazyHStack(spacing: spacing) {
                    Color.clear
                        .frame(width: geo.size.width * 0.15 - spacing)
                    ForEach(0..<viewCount, id: \.self) { idx in
                        views()[idx]
                            .frame(width: width)
                            .padding(.vertical)
                   }
                }
                .offset(x: CGFloat(-selectedTab) * (width + spacing) + offset)
                .animation(.easeOut, value: selectedTab)
                .gesture(
                    DragGesture()
                        .onChanged { value in
                            offset = value.translation.width
                        }
                        .onEnded { value in
                            withAnimation(.easeOut) {
                                offset = value.predictedEndTranslation.width
                                selectedTab -= Int((offset / width).rounded())
                                selectedTab = max(0, min(selectedTab, viewCount-1))
                                offset = 0
                            }
                        }
                )
            }
            //
            HStack {
                ForEach(0..<viewCount, id: \.self) { idx in
                    Circle().frame(width: 8)
                        .foregroundColor(idx == selectedTab ? .primary : .secondary.opacity(0.5))
                        .onTapGesture {
                            selectedTab = idx
                        }
                }
            }
        }
    }
}


struct TabContentView: View {
    
    let title: String
    let color: Color
    
    var body: some View {
        Text(title).font(.title)
            .padding()
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(color.opacity(0.4), ignoresSafeAreaEdges: .all)
            .clipShape(RoundedRectangle(cornerRadius: 20))
    }
}
Run Code Online (Sandbox Code Playgroud)