如何在 SwiftUI 中单击菜单项时隐藏浮动菜单

How to hide Floating Menu on Click of Menu Items in SwiftUI

我在 SwiftUI 中创建了浮动菜单,但我遇到了一个问题,当按下右下角的加号按钮时,我打开浮动菜单项,然后再次按下加号按钮隐藏浮动菜单项,但是当按下菜单项时它不会隐藏该菜单项。

下面是我的代码

MapContainerUIView.swift

struct MapContainerUIView: View {
    
    let flotingMenuArray = [
        MenuItemModel(title: "Camera", icon: "camera.fill"),
        MenuItemModel(title: "Photo", icon: "photo.on.rectangle"),
        MenuItemModel(title: "Share", icon: "square.and.arrow.up.fill")
    ]
    
    var body: some View {
        NavigationView{
            ZStack {
                FloatingMenu(dataSource: flotingMenuArray)
            }
        }
    }
    
    func floatingButtonAction(index: Int){
        print("Floating item tap", index)
    }
}

FloatingMenu.swift

struct FloatingMenu: View {
    init() {
        self.dataSource = []
    }
    
    init(dataSource: [MenuItemModel]) {
        self.dataSource = dataSource
    }
    
    @State var isMenuShow = false
    
    var dataSource: [MenuItemModel]
    
    var body: some View {
        
        ZStack(alignment: .trailing){
            if isMenuShow{
                Button(action: {
                    self.showMenu()
                }) {
                    Text("")
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .background(Color.black)
                        .opacity(0.3)
                }
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .edgesIgnoringSafeArea(.all)
            }
            HStack{
                Spacer()
                VStack(alignment: .trailing, content: {
                    Spacer()
                    ForEach(0..<dataSource.count) { index in
                        if isMenuShow {
                            MenuItems(menuItemData: dataSource[index], index: index)
                        }
                    }
                    Button(action: {
                        self.showMenu()
                    }) {
                        Image(systemName: "plus.circle.fill")
                            .resizable()
                            .frame(width: 60, height: 60)
                            .foregroundColor(Color.white)
                    }
                    .background(Color.black)
                    .cornerRadius(35)
                })
                .shadow(color: .gray, radius: 4, x: 1, y: 1)
                .padding(.init(top: 0, leading: 20, bottom: 20, trailing: 20))
            }
        }
    }
    
    func showMenu() {
        self.isMenuShow.toggle()
    }
}

MenuItems.swift

class MenuItemModel : Identifiable{
    var id = UUID()
    var title : String = ""
    var icon : String = ""
    
    init(title: String, icon: String) {
        self.title = title
        self.icon = icon
    }
}

struct MenuItems: View {
    var mapContainer = MapContainerUIView()
    var menuItemData: MenuItemModel
    var index : Int
    
    var body: some View {
        ZStack {
            HStack{
                Text(menuItemData.title)
                    .foregroundColor(.white)
                    .shadow(color: .gray, radius: 3, x: 1, y: 1)
                Button(action: {
                    FloatingMenu().isMenuShow = false
                    print("button tap: ", menuItemData.title)
                    self.mapContainer.floatingButtonAction(index: index)
                }) {
                    ZStack {
                        Circle()
                            .foregroundColor(Color.white)
                            .frame(width: 45, height: 45)
                            .shadow(color: .gray, radius: 3, x: 1, y: 1)
                        Image(systemName: menuItemData.icon)
                            .imageScale(.large)
                            .foregroundColor(.black)
                    }
                    .padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 10))
                }
            }
        }
    }
}

我想在按下菜单项时隐藏浮动菜单,请有人指导我。

现在,您正在尝试在 FloatingMenu 新实例 上设置 isMenuShow,这就是它不起作用的原因。

一个解决方案是从原始 FloatingMenu 实例传递一个 Binding

struct MenuItems: View {
    @Binding var isMenuShow : Bool  //<-- Here
    var mapContainer = MapContainerUIView()
    var menuItemData: MenuItemModel
    var index : Int
    
    var body: some View {
        ZStack {
            HStack{
                Text(menuItemData.title)
                    .foregroundColor(.white)
                    .shadow(color: .gray, radius: 3, x: 1, y: 1)
                Button(action: {
                    self.isMenuShow = false //<-- Here
                    print("button tap: ", menuItemData.title)
                    self.mapContainer.floatingButtonAction(index: index)
                }) {

并且,在浮动菜单中:

if isMenuShow {
  MenuItems(isMenuShow: $isMenuShow, //<-- Here
            menuItemData: dataSource[index],
            index: index)
}

另一个解决方案是提供一个闭包作为 MenuItems 的参数来关闭菜单:

struct MenuItems: View {
    var closeMenu : () -> Void //<-- Here
    var mapContainer = MapContainerUIView()
    var menuItemData: MenuItemModel
    var index : Int
    
    var body: some View {
        ZStack {
            HStack{
                Text(menuItemData.title)
                    .foregroundColor(.white)
                    .shadow(color: .gray, radius: 3, x: 1, y: 1)
                Button(action: {
                    closeMenu()  //<-- Here
                    print("button tap: ", menuItemData.title)
                    //self.mapContainer.floatingButtonAction(index: index)
                }) {
if isMenuShow {
    MenuItems(closeMenu: { self.isMenuShow = false },
              menuItemData: dataSource[index],
              index: index)
}