macOS文件对话框自定义视图accessoryView
macOS文件对话框自定义视图accessoryView

macOS文件对话框自定义视图accessoryView

accessoryView 是 NSOpenPanel 或 NSSavePanel 中的一个属性,允许文件对话框中底部添加一个自定义的视图(NSView),通常用于提供一些额外选项,比如:

1、文件格式选项(如 PNG / JPEG)。

2、导出设置(如压缩率、是否加密)。

3、说明文字或提示。

4、自定义操作按钮或开关。

基本用法

在NSOpenPanel 或 NSSavePanel中,创建一个自定义的视图,然后赋值给accessoryView属性。

let panel = NSSavePanel()
let formatPopup = NSPopUpButton(frame: NSRect(x: 0, y: 0, width: 200, height: 26))
formatPopup.addItems(withTitles: ["PNG", "JPEG", "TIFF"])
panel.accessoryView = formatPopup

在这个代码中,创建一个NSPopUpButton下拉列表,并配置三个选项。

赋值给NSSavePanel的accessoryView属性后,保存文件时,就会显示NSPopUpButton下拉列表。

完整示例

外部类:

class SavePanelController: NSObject {
    let panel = NSSavePanel()
    let formatPopup = NSPopUpButton(frame: NSRect(x: 0, y: 0, width: 200, height: 26))
    let extensions = ["png", "jpg", "tiff"]

    func showSavePanel() {
        formatPopup.addItems(withTitles: ["PNG", "JPEG", "TIFF"])
        formatPopup.target = self
        formatPopup.action = #selector(handleFormatChange)

        panel.accessoryView = formatPopup
        panel.allowedFileTypes = ["png"]
        panel.nameFieldStringValue = "image.png"

        if panel.runModal() == .OK, let url = panel.url {
            let selectedFormat = formatPopup.titleOfSelectedItem
            print("保存到: \(url.path)")
            print("选择格式: \(selectedFormat ?? "")")
        }
    }

    @objc func handleFormatChange(_ sender: NSPopUpButton) {
        let index = sender.indexOfSelectedItem
        let selectedExt = extensions[index]

        panel.allowedFileTypes = [selectedExt]
        let baseName = (panel.nameFieldStringValue as NSString).deletingPathExtension
        panel.nameFieldStringValue = "\(baseName).\(selectedExt)"
    }
}

在SwiftUI的Button中调用:

let controller = SavePanelController()

Button("保存文件") {
    controller.showSavePanel()
}

在 NSOpenPanel 或 NSSavePanel 底部添加一个 popup 按钮,供用户选择文件格式。

使用场景

1、选择导出格式:PNG / PDF / JPG 下拉菜单。

2、设置选项:勾选“启用加密”。

3、动态提示:显示选中文件是否合规。

4、扩展用户交互:添加“导出全部”按钮或进阶选项。

多控件视图

accessoryView实际上可以设置任意一个 NSView,这个视图可以包含多个控件,比如:文本、弹窗、复选框、滑块等。

可以把多个子控件嵌入到一个 NSView 中,然后赋值给accessoryView:

let container = NSView(frame: NSRect(x: 0, y: 0, width: 300, height: 80))

let formatLabel = NSTextField(labelWithString: "保存格式:")
formatLabel.frame = NSRect(x: 0, y: 50, width: 70, height: 20)

let formatPopup = NSPopUpButton(frame: NSRect(x: 80, y: 46, width: 200, height: 26))
formatPopup.addItems(withTitles: ["PNG", "JPEG", "TIFF"])

let checkbox = NSButton(checkboxWithTitle: "保留透明背景", target: nil, action: nil)
checkbox.frame.origin = CGPoint(x: 0, y: 10)

container.addSubview(formatLabel)
container.addSubview(formatPopup)
container.addSubview(checkbox)

panel.accessoryView = container

注意,在AppKit中,坐标的原点(0,0)默认位于左下角,不是SwiftUI的左上角原点。

↑ y轴
|
|       ┌───────────────┐   ← y:50(formatLabel)
|       │ 保存格式:     │
|       └───────────────┘
|               ┌────────────────────────┐   ← y:46(formatPopup)
|               │ [ PNG ▼ ]              │
|               └────────────────────────┘
|                                       
|   ┌───────────────────────────────┐    ← y:10(checkbox)
|   │ ☑ 保留透明背景                │
|   └───────────────────────────────┘
|
└────────────────────────────────────→ x轴
 (0, 0)

因此,在显示自定义视图时,保存格式和PNG的y分别为50和46,所以在同一行列,在保留透明背景的y为0,所以靠近底部的行列。

注意事项

1、accessoryView 只接受一个视图,但该视图中可以有多个子控件。

2、支持布局方式:手动布局或使用 NSStackView。

3、accessoryView在有些 macOS 版本默认折叠,可以尝试调用 isAccessoryViewDisclosed = true(但不总是有效)。

4、支持约束,可以设置 Auto Layout constraints,但需要注意 accessoryView 的固定大小。

总结

accessoryView 是 NSOpenPanel / NSSavePanel 底部的可扩展自定义视图,适合在文件选择对话框中提供附加选项或交互控件,是桌面应用中提升用户体验的利器。

相关文章

1、macOS文件选择对话框NSOpenPanel:https://fangjunyu.com/2025/06/27/macos%e6%96%87%e4%bb%b6%e9%80%89%e6%8b%a9%e5%af%b9%e8%af%9d%e6%a1%86nsopenpanel/

2、macOS保存文件的对话框NSSavePanel:https://fangjunyu.com/2025/06/27/macos%e4%bf%9d%e5%ad%98%e6%96%87%e4%bb%b6%e7%9a%84%e5%af%b9%e8%af%9d%e6%a1%86nssavepanel/

3、macOS下拉菜单NSPopUpButton:https://fangjunyu.com/2025/06/28/macos%e4%b8%8b%e6%8b%89%e8%8f%9c%e5%8d%95nspopupbutton/

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注