我想在 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 个按钮,例如设置、主要和关于我们。一旦用户点击“关于我们”,“关于我们”视图就会在 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()
}
}
这里是我找到的解决方案的链接,但我无法使其按照我想要的方式工作,但有所帮助。 https://stackoverflow.com/a/66933468/15284614
答案 0 :(得分:0)
这似乎符合您的要求:
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
维护侧边栏是否显示以及另一个视图的 NavigationLink 是否处于活动状态(通过自定义绑定)NavigationView
标题navigateToViewType
NavigationLink
仅在导航管理器中的视图类型设置为除 .main
以外的其他内容时才处于活动状态目前有一个过渡,当我回到主视图时,标题不是立即可见的,我并不为之疯狂,但这是您可以关注的细节工作。这应该会让你走上正确的道路