SwiftUI中的自定义菜单/选项卡栏

hfyxw5xn  于 2022-12-03  发布在  Swift
关注(0)|答案(1)|浏览(336)

我想做这样的标签栏,不知道从哪里开始。请帮助我,我是一个新手!
它导航到不同的视图。

pxq42qpu

pxq42qpu1#

这是一个非常实用的版本。它可以做得更好,以进一步镜像SwiftUI的TabBar界面。如果你遇到任何问题,请告诉我。

full res)(英文)

protocol TopTab: RawRepresentable, Identifiable, CaseIterable, Hashable where AllCases == Array<Self> {
    var title: String { get }
}

struct TabBackground: Shape {
    var cornerRadius: CGFloat = 8
    func path(in rect: CGRect) -> Path {
        var path = Path()
        path.move(to: CGPoint(x: .zero + cornerRadius, y: .zero))
        path.addLine(to: CGPoint(x: rect.width - cornerRadius, y: .zero))
        path.addQuadCurve(to: CGPoint(x: rect.width, y: .zero + cornerRadius), control: CGPoint(x: rect.width, y: .zero))
        path.addLine(to: CGPoint(x: rect.width, y: rect.height - cornerRadius))
        path.addQuadCurve(to: CGPoint(x: rect.width + cornerRadius, y: rect.height), control: CGPoint(x: rect.width, y: rect.height))
        path.addLine(to: CGPoint(x: .zero - cornerRadius, y: rect.height))
        path.addQuadCurve(to: CGPoint(x: .zero, y: rect.height - cornerRadius), control: CGPoint(x: .zero, y: rect.height))
        path.addLine(to: CGPoint(x: .zero, y: cornerRadius))
        path.addQuadCurve(to: CGPoint(x: .zero + cornerRadius, y: .zero), control: .zero)
        return path
    }
}

struct TopScrollingTabBarPicker<Tab: TopTab>: View {
    @Binding var selection: Tab
    
    var body: some View {
        
        ScrollView(.horizontal, showsIndicators: false) {
            LazyHStack {
                ForEach(Tab.allCases) { tab in
                    Group {
                        if tab == selection {
                            Text(tab.title)
                                .bold()
                                .foregroundColor(.accentColor)
                                .padding(12)
                                .background {
                                    TabBackground(cornerRadius: 16)
                                        .fill(Color.white)
                                }
                        } else {
                            Text(tab.title)
                                .padding(4)
                                .foregroundColor(.white)
                        }
                    }
                    .tag(tab)
                    .onTapGesture {
                        selection = tab
                    }
                }
            }
            .padding(.horizontal, 10)
        }
        .background(Color.accentColor)
    }
}

struct TopScrollingTabBar<Tab: TopTab, Content: View>: View {
    var alignment: HorizontalAlignment = .leading
    @Binding var selection: Tab
    @ViewBuilder var content: (_ tab: Tab) -> Content
    
    var body: some View {
        GeometryReader { geometry in
            VStack(alignment: alignment) {
                TopScrollingTabBarPicker(selection: $selection)
                    .frame(height: 44)
                ZStack {
                    Color(.systemBackground)
                        .ignoresSafeArea()
                    self.content(selection)
                        .transition(.asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing)))
                }
            }
        }
    }
}

用法:

enum PreviewTab: String, TopTab {
    case saved
    case booked
    case pending
    case confirmed
    case archived
    
    var id: String {
        rawValue
    }
    
    var title: String {
        switch self {
        case .saved:
            return "Saved"
        case .booked:
            return "Booked"
        case .pending:
            return "Pending"
        case .confirmed:
            return "Confirmed"
        case .archived:
            return "Archived"
        }
    }
}

struct ContentView: View {
    
    @State var selection: PreviewTab = .saved
    
    var body: some View {
        TopScrollingTabBar(selection: $selection.animation()) { tab in
            // For demo purposes
            List {
                Text(tab.title)
                    .bold()
                    .font(.largeTitle)
                Text("Something that is \(tab.title)")
            }
            .listStyle(.plain)
            
            // In a full app I'd switch on the Tab enum and generate the appropriate view.
//            switch tab {
//            case .saved:
//                SavedThings()
//            case .booked:
//                ...etc
//            }
        }
    }
}

希望这对你有帮助!〈3

相关问题