NSToolbar
是 macOS 应用中的一个重要控件,用于创建窗口顶部的工具栏。工具栏通常包含按钮和其他控件,用户可以通过这些控件快速访问常用功能。NSToolbar
和 NSToolbarItem
协同工作,NSToolbar
是工具栏容器,而 NSToolbarItem
是工具栏项。下面我们详细介绍 NSToolbar
的常见 API 和基础技巧。
基本使用
创建和初始化工具栏
Objective-C
#import <Cocoa/Cocoa.h>
// 创建一个 NSToolbar 实例
NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"MainToolbar"];
// 设置 Delegate
[toolbar setDelegate:self];
// 将工具栏添加到窗口
[self.window setToolbar:toolbar];
Swift
import Cocoa
// 创建一个 NSToolbar 实例
let toolbar = NSToolbar(identifier: "MainToolbar")
// 设置 Delegate
toolbar.delegate = self
// 将工具栏添加到窗口
self.window?.toolbar = toolbar
创建工具栏项
Objective-C
// 实现 NSToolbarDelegate 方法,返回所有允许在工具栏中使用的项
- (NSArray<NSString *> *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar {
return @[@"FirstItem", NSToolbarFlexibleSpaceItemIdentifier, @"SecondItem"];
}
// 实现 NSToolbarDelegate 方法,为特定标识符创建相应的工具栏项
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag {
if ([itemIdentifier isEqualToString:@"FirstItem"]) {
NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:@"FirstItem"];
item.label = @"First";
item.toolTip = @"First Tool";
item.action = @selector(handleToolbarAction:);
item.target = self;
item.image = [NSImage imageNamed:NSImageNameAddTemplate];
return item;
} else if ([itemIdentifier isEqualToString:@"SecondItem"]) {
NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:@"SecondItem"];
item.label = @"Second";
item.toolTip = @"Second Tool";
item.action = @selector(handleToolbarAction:);
item.target = self;
item.image = [NSImage imageNamed:NSImageNameRemoveTemplate];
return item;
}
return nil;
}
Swift
// 实现 NSToolbarDelegate 方法,返回所有允许在工具栏中使用的项
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
return [.init("FirstItem"), .flexibleSpace, .init("SecondItem")]
}
// 实现 NSToolbarDelegate 方法,为特定标识符创建相应的工具栏项
func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
if itemIdentifier.rawValue == "FirstItem" {
let item = NSToolbarItem(itemIdentifier: .init("FirstItem"))
item.label = "First"
item.toolTip = "First Tool"
item.action = #selector(handleToolbarAction(_:))
item.target = self
item.image = NSImage(named: NSImage.addTemplateName)
return item
} else if itemIdentifier.rawValue == "SecondItem" {
let item = NSToolbarItem(itemIdentifier: .init("SecondItem"))
item.label = "Second"
item.toolTip = "Second Tool"
item.action = #selector(handleToolbarAction(_:))
item.target = self
item.image = NSImage(named: NSImage.removeTemplateName)
return item
}
return nil
}
响应工具栏项点击事件
Objective-C
// 实现工具栏项的点击响应方法
- (void)handleToolbarAction:(id)sender {
NSToolbarItem *selectedItem = (NSToolbarItem *)sender;
NSLog(@"Selected item: %@", selectedItem.itemIdentifier);
}
Swift
// 实现工具栏项的点击响应方法
@objc func handleToolbarAction(_ sender: Any?) {
if let toolbarItem = sender as? NSToolbarItem {
print("Selected item: \(toolbarItem.itemIdentifier.rawValue)")
}
}
自定义工具栏项
可以通过子类化 NSToolbarItem
来创建自定义工具栏项。
Objective-C
@interface CustomToolbarItem : NSToolbarItem
@end
@implementation CustomToolbarItem
- (instancetype)initWithItemIdentifier:(NSString *)itemIdentifier {
self = [super initWithItemIdentifier:itemIdentifier];
if (self) {
// 自定义设置
self.label = @"Custom";
self.toolTip = @"Custom Tool";
self.image = [NSImage imageNamed:NSImageNameInfo];
}
return self;
}
@end
Swift
class CustomToolbarItem: NSToolbarItem {
override init(itemIdentifier: NSToolbarItem.Identifier) {
super.init(itemIdentifier: itemIdentifier)
// 自定义设置
self.label = "Custom"
self.toolTip = "Custom Tool"
self.image = NSImage(named: NSImage.infoTemplateName)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
动态更新工具栏项
可以通过设置工具栏项的 minSize
和 maxSize
以及使用 validateToolbarItem
方法来动态更新工具栏项。
Objective-C
- (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem {
if ([toolbarItem.itemIdentifier isEqualToString:@"FirstItem"]) {
// 根据条件禁用或启用工具栏项
return YES;
}
return YES;
}
// 更新工具栏项的大小
- (void)updateToolbarItemsSize {
NSToolbarItem *firstItem = [self.toolbar.items firstObject];
[firstItem setMinSize:NSMakeSize(30, 30)];
[firstItem setMaxSize:NSMakeSize(50, 50)];
}
Swift
func validateToolbarItem(_ item: NSToolbarItem) -> Bool {
if item.itemIdentifier.rawValue == "FirstItem" {
// 根据条件禁用或启用工具栏项
return true
}
return true
}
// 更新工具栏项的大小
func updateToolbarItemsSize() {
if let firstItem = toolbar.items.first {
firstItem.minSize = NSSize(width: 30, height: 30)
firstItem.maxSize = NSSize(width: 50, height: 50)
}
}
隐藏和显示工具栏
可以通过 setVisible:
方法控制工具栏的显示和隐藏。
Objective-C
// 隐藏工具栏
[self.window.toolbar setVisible:NO];
// 显示工具栏
[self.window.toolbar setVisible:YES];
Swift
// 隐藏工具栏
self.window?.toolbar?.isVisible = false
// 显示工具栏
self.window?.toolbar?.isVisible = true
高级用法
自定义工具栏项视图
可以自定义工具栏项的视图,比如将 NSButton 作为工具栏项。
Objective-C
- (NSToolbarItem *)createCustomViewToolbarItemWithIdentifier:(NSString *)identifier label:(NSString *)label action:(SEL)action {
NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:identifier];
item.label = label;
item.view = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 30)];
NSButton *button = (NSButton *)item.view;
[button setTitle:label];
[button setTarget:self];
[button setAction:action];
return item;
}
Swift
func createCustomViewToolbarItem(identifier: NSToolbarItem.Identifier, label: String, action: Selector) -> NSToolbarItem {
let item = NSToolbarItem(itemIdentifier: identifier)
item.label = label
let button = NSButton(frame: NSRect(x: 0, y: 0, width: 100, height: 30))
button.title = label
button.target = self
button.action = action
item.view = button
return item
}
动态添加和移除工具栏项
Objective-C
// 动态添加工具栏项
- (void)addToolbarItemWithIdentifier:(NSString *)identifier {
NSToolbarItem *newItem = [self toolbar:nil itemForItemIdentifier:identifier willBeInsertedIntoToolbar:YES];
[self.toolbar insertItemWithItemIdentifier:identifier atIndex:self.toolbar.items.count];
}
// 动态移除工具栏项
- (void)removeToolbarItemWithIdentifier:(NSString *)identifier {
for (NSToolbarItem *item in self.toolbar.items) {
if ([item.itemIdentifier isEqualToString:identifier]) {
[self.toolbar removeItemAtIndex:[self.toolbar.items indexOfObject:item]];
break;
}
}
}
Swift
// 动态添加工具栏项
func addToolbarItem(identifier: NSToolbarItem.Identifier) {
if let newItem = self.toolbar(nil, itemForItemIdentifier: identifier, willBeInsertedIntoToolbar: true) {
toolbar.insertItem(withItemIdentifier: identifier, at: toolbar.items.count)
}
}
// 动态移除工具栏项
func removeToolbarItem(identifier: NSToolbarItem.Identifier) {
for (item in toolbar.items) {
if item.itemIdentifier == identifier {
if let index = toolbar.items.firstIndex(of: item) {
toolbar.removeItem(at: index)
break
}
}
}
}
工具栏定制面板
macOS 提供了工具栏定制功能,用户可以通过它自行选择工具栏中的项。
Objective-C
// 允许工具栏定制
[toolbar setAllowsUserCustomization:YES];
// 实现代理方法,返回用户定制时可以看到的项
- (NSArray<NSString *> *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar {
return @[@"FirstItem", NSToolbarFlexibleSpaceItemIdentifier, @"SecondItem"];
}
- (NSArray<NSString *> *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar {
return @[@"FirstItem", NSToolbarFlexibleSpaceItemIdentifier, @"SecondItem", @"CustomItem"];
}
Swift
// 允许工具栏定制
toolbar.allowsUserCustomization = true
// 实现代理方法,返回用户定制时可以看到的项
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
return [.init("FirstItem"), .flexibleSpace, .init("SecondItem")]
}
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
return [.init("FirstItem"), .flexibleSpace, .init("SecondItem"), .init("CustomItem")]
}
封装工具类
为了更方便地使用 NSToolbar
,可以封装一个工具类,提供常见功能的高层接口。
Objective-C
#import <Cocoa/Cocoa.h>
@interface NSToolbarHelper : NSObject
+ (NSToolbar *)createToolbarWithIdentifier:(NSString *)identifier delegate:(id<NSToolbarDelegate>)delegate;
+ (NSToolbarItem *)createToolbarItemWithIdentifier:(NSString *)identifier label:(NSString *)label action:(SEL)action target:(id)target image:(NSImage *)image;
@end
@implementation NSToolbarHelper
+ (NSToolbar *)createToolbarWithIdentifier:(NSString *)identifier delegate:(id<NSToolbarDelegate>)delegate {
NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:identifier];
[toolbar setDelegate:delegate];
[toolbar setAllowsUserCustomization:YES];
return toolbar;
}
+ (NSToolbarItem *)createToolbarItemWithIdentifier:(NSString *)identifier label:(NSString *)label action:(SEL)action target:(id)target image:(NSImage *)image {
NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:identifier];
item.label = label;
item.toolTip = label;
item.image = image;
item.action = action;
item.target = target;
return item;
}
@end
Swift
import Cocoa
class NSToolbarHelper {
// 创建 NSToolbar 并设置代理
static func createToolbar(identifier: String, delegate: NSToolbarDelegate) -> NSToolbar {
let toolbar = NSToolbar(identifier: NSToolbar.Identifier(identifier))
toolbar.delegate = delegate
toolbar.allowsUserCustomization = true
return toolbar
}
// 创建 NSToolbarItem
static func createToolbarItem(identifier: String, label: String, action: Selector, target: AnyObject, image: NSImage) -> NSToolbarItem {
let item = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier(identifier))
item.label = label
item.toolTip = label
item.image = image
item.action = action
item.target = target
return item
}
}
使用示例
Objective-C
// 创建 NSToolbar
NSToolbar *toolbar = [NSToolbarHelper createToolbarWithIdentifier:@"MainToolbar" delegate:self];
[self.window setToolbar:toolbar];
// 创建并添加工具栏项
NSToolbarItem *firstItem = [NSToolbarHelper createToolbarItemWithIdentifier:@"FirstItem" label:@"First" action:@selector(handleToolbarAction:) target:self image:[NSImage imageNamed:NSImageNameAddTemplate]];
[toolbar insertItemWithItemIdentifier:@"FirstItem" atIndex:0];
NSToolbarItem *secondItem = [NSToolbarHelper createToolbarItemWithIdentifier:@"SecondItem" label:@"Second" action:@selector(handleToolbarAction:) target:self image:[NSImage imageNamed:NSImageNameRemoveTemplate]];
[toolbar insertItemWithItemIdentifier:@"SecondItem" atIndex:1];
Swift
// 创建 NSToolbar
let toolbar = NSToolbarHelper.createToolbar(identifier: "MainToolbar", delegate: self)
self.window?.toolbar = toolbar
// 创建并添加工具栏项
let firstItem = NSToolbarHelper.createToolbarItem(identifier: "FirstItem", label: "First", action: #selector(handleToolbarAction(_:)), target: self, image: NSImage(named: NSImage.addTemplateName)!)
toolbar.insertItem(withItemIdentifier: NSToolbarItem.Identifier("FirstItem"), at: 0)
let secondItem = NSToolbarHelper.createToolbarItem(identifier: "SecondItem", label: "Second", action: #selector(handleToolbarAction(_:)), target: self, image: NSImage(named: NSImage.removeTemplateName)!)
toolbar.insertItem(withItemIdentifier: NSToolbarItem.Identifier("SecondItem"), at: 1)
总结
通过了解 NSToolbar
的基本使用、创建工具栏项、响应工具栏项选择、自定义工具栏项、动态更新工具栏项、隐藏和显示工具栏以及工具栏定制面板等高级用法,并封装工具类,你将能够更高效地使用 NSToolbar
创建复杂的工具栏系统。在实际应用中,合理使用这些技巧可以显著提升用户界面的灵活性和用户体验。希望本文对你有所帮助,