SwiftUI中的侧菜单栏

SwiftUI中的侧菜单栏,swift,swiftui,Swift,Swiftui,我想在SwiftUI中创建一个侧菜单栏 //下面是我想用于内容视图的自定义栏视图的代码 VStack { ZStack { VStack { Button(action: { withAnimation { sidebarShowns.toggle()

我想在SwiftUI中创建一个侧菜单栏

//下面是我想用于内容视图的自定义栏视图的代码

VStack {
            ZStack {
                VStack {
                    Button(action: {
                        withAnimation {
                            sidebarShowns.toggle()
                        }
                    }) {
                        Image(systemName: "line.horizontal.3")
                            .font(.headline)
                        }.padding(.leading)
                    }.frame(maxWidth: .infinity, alignment: .leading)
                    
                    Text("WeCollab")
                        .foregroundColor(.white)
                        .font(.title)
                }
                .background(Color.purple.edgesIgnoringSafeArea(.top))
       }
}
我希望侧菜单栏视图使用此自定义栏,一旦用户点击3条水平线图标,自定义侧菜单栏将在屏幕左侧打开

我希望它能像这样工作,一旦通过点击3条水平线图标打开侧菜单栏,用户就会看到3个按钮,如设置、主和关于我们。一旦用户点击例如about us,about us视图将在iPhone屏幕上完全打开,自定义栏将隐藏,侧菜单将自动关闭。用户将使用后退按钮“此后退按钮使用左V形图标”导航回原始视图

我不希望每个视图上都有自定义栏,也不希望每个视图中都有侧菜单

我希望能够为每个视图使用一个SwiftUI视图文件来实现这一点,该视图将作为侧菜单栏中的按钮链接到每个视图

//我有一些代码的示例,但没有按照我希望的方式工作

import SwiftUI

enum ViewTypesz {
    case main
    case settings
    case aboutUs
    
}

class SidebarNavigationManagerz : ObservableObject {
    @Published var viewType : ViewTypesz = .main
}


struct testView: View {
    @State private var sidebarShowns = false
    @StateObject var navigationManagers = SidebarNavigationManagerz()
    
    var body: some View {
        ZStack(alignment: .topLeading) {
            if sidebarShowns {
                SidebarView(navigationManagers: navigationManagers)
                    .frame(width: 250)
                    .frame(maxHeight: .infinity)
                    .border(Color.red)
                    .transition(sidebarShowns ? .move(edge: .leading) : .move(edge: .trailing) )
                        .background(customBlueColour)
                        .opacity(60.0)
                        }
        VStack {
            ZStack {
                VStack {
                    Button(action: {
                        withAnimation {
                            sidebarShowns.toggle()
                        }
                    }) {
                        Image(systemName: "line.horizontal.3")
                            .font(.headline)
                        }.padding(.leading)
                    }.frame(maxWidth: .infinity, alignment: .leading)
                    
                    Text("WeCollab")
                        .foregroundColor(.white)
                        .font(.title)
                }
                .background(Color.purple.edgesIgnoringSafeArea(.top))
                
                VStack {
                    switch navigationManagers.viewType {
                    case .main:
                        MainView()
                    case .settings:
                        SettingsViewz(navigationManagers: navigationManagers)
                    case .aboutUs:
                        AboutUsView()
                   // case .homeview:
                     //   HomeView()
                    }
                }.frame(maxHeight: .infinity)
            }.frame(maxWidth: .infinity, maxHeight: .infinity)
            
        }                                .edgesIgnoringSafeArea(.top)

        
    }
}

struct SidebarView : View {
    @ObservedObject var navigationManagers : SidebarNavigationManagerz
    
    var body: some View {
        //Sidebar
        VStack {
            Button(action: { navigationManagers.viewType = .main }) {
                Text("Main")
            }
            Button(action: { navigationManagers.viewType = .settings }) {
                Text("Settings")
            }
            Button(action: { navigationManagers.viewType = .aboutUs }) {
                Text("About Us")
            }
        }
    }
}

struct MainView : View {
    var body: some View {
        Text("Main")
            
    }
}

struct SettingsViewz: View {
    @ObservedObject var navigationManagers : SidebarNavigationManagerz
    
    var body: some View {
        Text("Settings")
        Button("Go home") {
            navigationManagers.viewType = .settings
        }
    }
}

struct AboutUsView : View {
    var body: some View {
        Text("About Us")
    }
}
struct testView_Previews: PreviewProvider {
    static var previews: some View {
        testView()
    }
}
这里有一个链接,指向我找到的一个解决方案,但我无法使它按照我想要的方式工作,但我提供了帮助。

这似乎是你想要的:


enum ViewTypesz {
    case main
    case settings
    case aboutUs
    
}

class SidebarNavigationManagerz : ObservableObject {
    @Published var viewType : ViewTypesz = .main
    @Published var sidebarShown = false
    
    func navigateToViewType(_ type: ViewTypesz) {
        viewType = type
        sidebarShown = false
    }
    
    @ViewBuilder var viewForType : some View {
        switch viewType {
        case .main:
            EmptyView()
        case .aboutUs:
            AboutUsView()
        case .settings:
            SettingsViewz()
        }
    }
    
    var bindingForNavLink : Binding<Bool> {
        .init { () -> Bool in
            return self.viewType != .main
        } set: { (newValue) in
            if !newValue { self.viewType = .main }
        }

    }
}


struct ContentView: View {
    @StateObject var navigationManagers = SidebarNavigationManagerz()
    
    var body: some View {
        NavigationView {
            if navigationManagers.viewType != .main {
                NavigationLink(destination: navigationManagers.viewForType, isActive: navigationManagers.bindingForNavLink, label: { EmptyView() })
            }
            
            VStack(alignment: .leading) {
                ZStack {
                    VStack {
                        Button(action: {
                            withAnimation {
                                navigationManagers.sidebarShown.toggle()
                            }
                        }) {
                            Image(systemName: "line.horizontal.3")
                                .font(.headline)
                        }.padding(.leading)
                    }.frame(maxWidth: .infinity, alignment: .leading)
                    
                    Text("WeCollab")
                        .foregroundColor(.white)
                        .font(.title)
                }
                .background(Color.purple.edgesIgnoringSafeArea(.top))
                
                ZStack(alignment: .topLeading) {
                    VStack(alignment: .center) {
                        MainView()
                    }
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    
                    if navigationManagers.sidebarShown {
                        SidebarView(navigationManagers: navigationManagers)
                            .frame(width: 250)
                            .frame(maxHeight: .infinity)
                            .border(Color.red)
                            .transition(navigationManagers.sidebarShown ? .move(edge: .leading) : .move(edge: .trailing) )
                            .background(Color.white)
                            .opacity(60.0)
                    }
                }
            }.frame(maxWidth: .infinity, maxHeight: .infinity)
            .navigationBarHidden(true)
        }.navigationViewStyle(StackNavigationViewStyle())
    }
}

struct SidebarView : View {
    @ObservedObject var navigationManagers : SidebarNavigationManagerz
    
    var body: some View {
        VStack {
            Button(action: { navigationManagers.navigateToViewType(.aboutUs) }) {
                Text("About us")
            }
            Button(action: { navigationManagers.navigateToViewType(.settings) }) {
                Text("Settings")
            }
        }
    }
}

struct MainView : View {
    var body: some View {
        Text("Main")
        
    }
}

struct SettingsViewz: View {
    var body: some View {
        Text("Settings")
    }
}

struct AboutUsView : View {
    var body: some View {
        Text("About Us")
    }
}


枚举视图类型{
主箱
案例设置
关于
}
类SidebarNavigationManagerz:ObserveObject{
@已发布的变量viewType:ViewTypesz=.main
@已发布的变量SidebarShowed=false
func navigateToViewType(type:ViewTypesz){
视图类型=类型
侧边栏显示=false
}
@ViewBuilder var viewForType:某些视图{
切换视图类型{
主要案例:
EmptyView()
案例.关于:
AboutUsView()
案例设置:
setingsviewz()
}
}
var bindingForNavLink:绑定{
.init{()->Bool-in
返回self.viewType!=.main
}集合:{(newValue)在
如果!newValue{self.viewType=.main}
}
}
}
结构ContentView:View{
@StateObject变量navigationManagers=SidebarNavigationManagerz()
var body:一些观点{
导航视图{
如果navigationManagers.viewType!=.main{
NavigationLink(目标:NavigationManager.viewForType,isActive:NavigationManager.bindingForNavLink,标签:{EmptyView()})
}
VStack(对齐:。前导){
ZStack{
VStack{
按钮(操作:{
动画片{
navigationManagers.SidebarShowed.toggle()
}
}) {
图像(系统名称:“line.horizontal.3”)
.font(.headline)
}.padding(.leading)
}.frame(最大宽度:。无穷大,对齐:。前导)
文本(“WeCollab”)
.foregroundColor(.白色)
.font(.title)
}
.背景(颜色.紫色.边缘识别安全区域(.top))
ZStack(对齐:。顶部引导){
VStack(对齐:。中心){
MainView()
}
.frame(maxWidth:无穷大,maxHeight:无穷大)
如果显示navigationManagers.sidebar{
侧栏视图(NavigationManager:NavigationManager)
.框架(宽度:250)
.frame(最大高度:。无穷大)
.边框(颜色.红色)
.transition(navigationManagers.SidebarShowed?.move(边:。前导):.move(边:。后导))
.背景(颜色.白色)
.不透明度(60.0)
}
}
}.frame(maxWidth:无穷大,maxHeight:无穷大)
.navigationBarHidden(真)
}.navigationViewStyle(StackNavigationViewStyle())
}
}
结构侧边栏视图:视图{
@观察对象变量导航管理器:SidebarNavigationManagerz
var body:一些观点{
VStack{
按钮(操作:{NavigationManager.navigateToViewType(.aboutUs)}){
文本(“关于我们”)
}
按钮(操作:{NavigationManager.navigateToViewType(.settings)}){
文本(“设置”)
}
}
}
}
结构主视图:视图{
var body:一些观点{
正文(“主要”)
}
}
结构设置视图:视图{
var body:一些观点{
文本(“设置”)
}
}
结构AboutsView:View{
var body:一些观点{
文本(“关于我们”)
}
}
工作原理:

  • SidebarNavigationManagerz
    维护是否显示侧栏以及另一个视图的导航链接是否处于活动状态(通过自定义绑定)
  • 主视图具有侧栏和自定义标题,而
    导航视图的标题隐藏
  • 侧栏链接触发导航视图类型
  • 主页上有一个
    NavigationLink
    ,只有当导航管理器中的视图类型设置为
    .main

  • 当前有一个过渡我并不热衷于返回到主视图,在主视图中标题不立即可见,但这是您可以关注的细节工作。这应该会让你走上正确的道路

    @jnpdx也许你能帮上忙。我正在调整给定的代码,它崩溃了,idk为什么。我的设置方式是为我要导航到的每个视图都有一个ui视图文件。以及侧菜单的普通swift文件;侧菜单文件包含视图类型和类SidebarNavigationManagerz。为什么我要设置它,使所有代码都不在一个视图文件中。