SwiftUI 菜单中的内联水平按钮

ada*_*ges 9 menu ios swift swiftui ipados

在 SwiftUI 中,有一个叫做菜单的东西,在里面你可以有按钮、分隔符、其他菜单等。下面是我正在构建的一个示例:

\n
import SwiftUI\n\nfunc testing() {\n    print("Hello")\n}\n\nstruct ContentView: View {\n    var body: some View {\n        VStack {\n            Menu {\n                Button(action: testing) {\n                    Label("Button 1", systemImage: "pencil.tip.crop.circle.badge.plus")\n                }\n                Button(action: testing) {\n                    Label("Button 2", systemImage: "doc")\n                }\n            }\n        label: {\n            Label("", systemImage: "ellipsis.circle")\n        }\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

因此,在 SwiftUI Playgrounds 应用程序中,他们有这个菜单:

\n

在此输入图像描述

\n

我的问题是:

\n

他们是如何制作圆圈菜单选项的?我\xe2\x80\x99在菜单中发现了这组水平按钮的其他一些情况,如下所示:

\n

在此输入图像描述

\n

HStacks 和其他明显的尝试都失败了。我\xe2\x80\x99ve查看了添加MenuStyle,但是Apple\xe2\x80\x99s文档非常缺乏,仅显示了向菜单按钮添加红色边框的示例。无论如何,不​​确定 \xe2\x80\x99 是正确的路径。

\n

I\xe2\x80\x99ve 只能让 Dividers() 和 Buttons() 显示在菜单中:

\n

在此输入图像描述

\n

尽管在应用程序中看到了其他选项的示例,但我\xe2\x80\x99也只能找到显示这两个选项的代码示例。

\n

zum*_*zum 11

iOS17开始,我可以通过使用Menu.

Menu {
                        
    ControlGroup {

        Button {
                                
        } label: {
            Image(systemName: "1.circle.fill")
        }

        Button {
                                
        } label: {
            Image(systemName: "2.circle.fill")
        }

        Button {
                                
        } label: {
            Image(systemName: "3.circle.fill")
        }

                           
    }
 
 ....

}
Run Code Online (Sandbox Code Playgroud)


Ash*_*lls 5

看起来这仅在UIKit目前(并且仅 iOS 16+)中可用,通过设置

menu.preferredElementSize = .medium
Run Code Online (Sandbox Code Playgroud)

要将其添加到您的应用程序中,您可以添加一个UIMenuto UIButton,然后使用UIHostingController将其添加到您的 SwiftUI 应用程序中。

这是一个示例实现:

子类化 UIButton

class MenuButton: UIButton {
    
    override init(frame: CGRect) {
        super.init(frame: frame)

        let inspectAction = self.inspectAction()
        let duplicateAction = self.duplicateAction()
        let deleteAction = self.deleteAction()

        setImage(UIImage(systemName: "ellipsis.circle"), for: .normal)
        menu = UIMenu(title: "", children: [inspectAction, duplicateAction, deleteAction])
        menu?.preferredElementSize = .medium
        showsMenuAsPrimaryAction = true

    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func inspectAction() -> UIAction {
        UIAction(title: "Inspect",
                 image: UIImage(systemName: "arrow.up.square")) { action in
           //
        }
    }
        
    func duplicateAction() -> UIAction {
        UIAction(title: "Duplicate",
                 image: UIImage(systemName: "plus.square.on.square")) { action in
           //
        }
    }
        
    func deleteAction() -> UIAction {
        UIAction(title: "Delete",
                 image: UIImage(systemName: "trash"),
            attributes: .destructive) { action in
           //
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

Menu使用 UIViewRepresentable创建一个

struct Menu: UIViewRepresentable {
    func makeUIView(context: Context) -> MenuButton {
        MenuButton(frame: .zero)
    }
    
    func updateUIView(_ uiView: MenuButton, context: Context) {
    }
}

Run Code Online (Sandbox Code Playgroud)

奇迹般有效!

struct ContentView: View {
    var body: some View {
        Menu()
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 苹果有一个完整的可下载项目,其中包含各种菜单。我建议安装它并看看它们会做什么。https://developer.apple.com/documentation/uikit/uicontrol/adding_context_menus_in_your_app (2认同)