【问题标题】:Show different views from NavigationBarItem menu in SwiftUI在 SwiftUI 中从 NavigationBarItem 菜单显示不同的视图
【发布时间】:2021-02-10 10:46:52
【问题描述】:

我正在尝试根据在 NavigationBar 菜单中选择的选项显示不同的视图。我被困在最好的方法上。 首先,根据我目前的做法(我认为这不对!),当我按下菜单项时,我在 Xcode 调试器中收到一条消息:

SideMenu[16587:1131441] [UILog] 调用 -[UIContextMenuInteraction updateVisibleMenuWithBlock:] 而没有可见的上下文菜单。这 不会做任何事情。

我该如何解决这个问题?

其次,当我从菜单中选择一个选项时,如何重置 bool 以便它不会被执行,除非再次从菜单中选择它。尝试在 if 条件内重置为 self.showNewView = false 会导致编译器错误

这是我正在尝试使用的完整可执行示例代码。感谢解决此问题的任何帮助。谢谢!

struct ContentView: View {
    @State var showNewView = false
    @State var showAddView = false
    @State var showEditView = false
    @State var showDeleteView = false
    
    var body: some View {
        NavigationView {
            GeometryReader { g in
                VStack {
                    if self.showAddView {
                        AddView()
                    }
                    if self.showNewView {
                        NewView()
                    }
                    if self.showEditView {
                        EditView()
                    }
                    if self.showDeleteView {
                        DeleteView()
                    }
                }.frame(width: g.size.width, height: g.size.height)
            }
            .navigationTitle("Title")
            .navigationBarItems(leading: {
                Menu {
                    Button(action: {showNewView.toggle()}) {
                        Label("New", systemImage: "pencil")
                    }
                    Button(action: {showEditView.toggle()}) {
                        Label("Edit", systemImage: "square.and.pencil")
                    }
                } label: {
                    Image(systemName: "ellipsis.circle")
                }
            }(), trailing: {
                Menu {
                    Button(action: {showAddView.toggle()}) {
                        Label("Add", systemImage: "plus")
                    }
                    Button(action: {showDeleteView.toggle()}) {
                        Label("Delete", systemImage: "trash")
                    }
                } label: {
                    Image(systemName: "plus")
                }
            }())
        }
        .navigationBarTitleDisplayMode(.inline)
        .navigationViewStyle(StackNavigationViewStyle())
    }
}



struct NewView: View {
    var body: some View {
        GeometryReader { g in
                Text("This is New View")
        }
        .background(Color.red)
    }
}

struct EditView: View {
    var body: some View {
        GeometryReader { g in
            Text("This is Edit View")
        }
        .background(Color.green)
    }
}

struct AddView: View {
    var body: some View {
        GeometryReader { g in
            Text("This is Add View")
        }
        .background(Color.orange)
    }
}

struct DeleteView: View {
    var body: some View {
        GeometryReader { g in
            Text("This is Delete View")
        }
        .background(Color.purple)
    }
}

这是我选择每个菜单项时得到的结果。我希望能够只显示一个菜单项。 Essentially dismiss the other one when a new menu item is selected

【问题讨论】:

  • 您编写了导航,但在您的代码中只是显示/隐藏子视图,那么您真正打算做什么?
  • 我想显示选定的视图。例如,如果我从菜单中选择“新建”,我想切换到“新建视图”
  • 更新主题为“显示不同的视图”

标签: ios swift swiftui


【解决方案1】:

一种可能的解决方案是为您的 current 视图使用专用枚举(而不是四个 @State 属性):

enum CurrentView {
    case new, add, edit, delete
}
@State var currentView: CurrentView?

请注意,您还可以将部分代码提取到计算属性中。


这是完整的代码:

enum CurrentView {
    case new, add, edit, delete
}

struct ContentView: View {
    @State var currentView: CurrentView?

    var body: some View {
        NavigationView {
            GeometryReader { g in
                content
                    .frame(width: g.size.width, height: g.size.height)
            }
            .navigationTitle("Title")
            .navigationBarTitleDisplayMode(.inline)
            .navigationBarItems(leading: leadingBarItems, trailing: trailingBarItems)
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
    
    @ViewBuilder
    var content: some View {
        if let currentView = currentView {
            switch currentView {
            case .add:
                AddView()
            case .new:
                NewView()
            case .edit:
                EditView()
            case .delete:
                DeleteView()
            }
        }
    }
    
    var leadingBarItems: some View {
        Menu {
            Button(action: { currentView = .new }) {
                Label("New", systemImage: "pencil")
            }
            Button(action: { currentView = .edit }) {
                Label("Edit", systemImage: "square.and.pencil")
            }
        } label: {
            Image(systemName: "ellipsis.circle")
        }
    }
    
    
    var trailingBarItems: some View {
        Menu {
            Button(action: { currentView = .add }) {
                Label("Add", systemImage: "plus")
            }
            Button(action: { currentView = .delete }) {
                Label("Delete", systemImage: "trash")
            }
        } label: {
            Image(systemName: "plus")
        }
    }
}

【讨论】:

  • 感谢您的回答!您很好地构建了代码并解决了第二个问题。但是,我在调试窗口中仍然有警告“SideMenu[1282:33494] [UILog] Called -[UIContextMenuInteraction updateVisibleMenuWithBlock:] 而没有可见的上下文菜单。这不会做任何事情”。任何解决此问题的指示?然后我可以接受你的回答
  • @RXP 这是一些内部警告/错误消息,但看起来它不会影响任何东西。即使您只使用菜单创建一个空的项目/视图,您也会看到这一点。你可以忽略这个。
  • 谢谢,希望他们能解决这个问题。在调试窗口中看到警告很烦人。
猜你喜欢
  • 2020-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多