SwiftUI 菜单 - 菜单实际打开时的操作

Mik*_*nko 17 menu haptic-feedback swiftui

我的应用程序中有一个菜单,当菜单打开时(通过onTagGesture操作)我会触发触觉反馈。

然而, 有时当我点击菜单打开触发器时,菜单实际上不会打开,但我仍然收到触觉反馈。我只在菜单实际打开时才需要触觉。

这是代码简化的代码块:

Menu {
    Button("Menu button", action: someAction}}
} label: { 
    Text("Open menu") //in reality, this a more complicated view tapping on which should open the (context) menu
}
.onTagGesture {
  let generator = UIImpactFeedbackGenerator(style: .rigid)
  generator.impactOccurred()
}
Run Code Online (Sandbox Code Playgroud)

所以它非常简单 - 点击触发器Open menu,点击被注册,触觉被回放,菜单打开。

但如前所述,无论出于何种原因,有时我按下该Open menu元素,触觉会回放,但实际菜单不会打开。

无论出于何种原因,我想知道一旦菜单实际打开(或者更好的是,实际打开),是否有任何方法可以执行操作(例如前面提到的触觉反馈)?我试图尽可能地寻找,但一无所获。

这也很重要,因为菜单也需要长按才能打开,这是打开菜单的 iOS 标准操作。即使我可以为长按添加另一个单独的处理程序(为两种情况提供触觉),但这似乎根本不是一个正确的方法。

结合有时菜单无法打开的事实,我似乎确实需要一些其他解决方案。任何人都可以分享任何想法吗?我是否缺少某种 onXXXXX 处理程序,该处理程序会在菜单打开时触发?

谢谢!

PS:为了提供更多细节,我正在尝试对 Apple 开发文档中描述的菜单实现这种方法: https: //developer.apple.com/documentation/swiftui/menu

作为该过程的一部分,我尝试将 onAppear 处理程序附加到整个菜单以及菜单内的单个元素。似乎两者都不起作用。

Menu {
    Button("Open in Preview", action: openInPreview)
    Button("Save as PDF", action: saveAsPDF)
        .onAppear { doHaptic() } //only fires once, when menu opens, but not for subsequent appearances
} label: {
    Label("PDF", systemImage: "doc.fill")
}
.onAppear { doHaptic() } //doesn't really as it fires when the menu itself appears on the screen as a child of a parent view.
Run Code Online (Sandbox Code Playgroud)

Asp*_*eri 5

以下变体似乎有效(使用 Xcode 13.3 / iOS 15.4 测试)

    Menu {
        Button("Open in Preview", action: {})
        Button("Save as PDF", action: {})
    } label: {
        Label("PDF", systemImage: "doc.fill")
    }
    .contentShape(Rectangle())
    .simultaneousGesture(TapGesture().onEnded {
        print(">> tapped")
    })
Run Code Online (Sandbox Code Playgroud)

*但是,请注意,手势不仅在点击打开时得到解决,而且在点击关闭时也得到解决。

  • 无需使用同时手势。只需一个简单的 onTapGesture() 即可完成这项工作。 (3认同)

Sim*_*mon 0

你可以用onAppear它。在菜单上使用它,只有当菜单出现时才会调用它。例如下面:

struct ContentView: View {
    
    @State var menuOpen: Bool = false
    
    // Just your button that triggers the menu
    var body: some View {
        Button(action: {
            self.menuOpen.toggle()
        }) {
            if menuOpen {
                MenuView(menuOpen: $menuOpen)
            } else {
                Image(systemName: "folder")
            }
        }
    }
}


struct MenuView: View {
    
    @Binding var menuOpen: Bool
    // the menu view
    var body: some View {
        Rectangle()
            .frame(width: 200, height: 200)
            .foregroundColor(Color.red)
            .overlay(Text("Menu Open").foregroundColor(Color.white))
            .onAppear(perform: self.impactFeedback) // <- Use onAppear on the menu view to trigger it
    }
    
    // if function called it triggers the impact
    private func impactFeedback() {
        let generator = UIImpactFeedbackGenerator(style: .rigid)
        generator.impactOccurred()
        print("triggered impact")
    }
}

Run Code Online (Sandbox Code Playgroud)

在 Xcode 12.4 上测试并运行

  • 谢谢,但这不是我想要使用的结构。您正在为有按钮的情况提出一个解决方案,该按钮又显示或隐藏子视图。我认为这会很好地工作,因为视图实际上是作为流程的一部分构建和销毁的(并触发“onAppear”)操作。我正在尝试获取实际菜单结构的触觉反馈,如下所述:https://developer.apple.com/documentation/swiftui/menu 如果我将 onAppear 处理程序放在 Menu() 结构本身上,它只会触发一次当菜单触发器作为父视图的一部分进入视图时。 (5认同)