Mac开发基础22-NSTabView

NSTabView 是 macOS 应用中的一个重要控件,用于创建带有多个选项卡的界面,类似于网页浏览器的选项卡功能。它能够将多个视图容器合并到一个控件中,每个视图容器都可以通过选项卡来切换。

基本使用

创建和初始化

Objective-C

#import <Cocoa/Cocoa.h>

// 创建一个 NSTabView 实例
NSTabView *tabView = [[NSTabView alloc] initWithFrame:NSMakeRect(0, 0, 600, 400)];

Swift

import Cocoa

// 创建一个 NSTabView 实例
let tabView = NSTabView(frame: NSRect(x: 0, y: 0, width: 600, height: 400))

添加标签页

Objective-C

// 创建第一个 TabViewItem
NSTabViewItem *firstTab = [[NSTabViewItem alloc] initWithIdentifier:@"firstTab"];
[firstTab setLabel:@"First Tab"];  // 设置标签页名称
NSView *firstView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 600, 400)];
[firstView setWantsLayer:YES];
[firstView.layer.backgroundColor = [NSColor redColor].CGColor];
[firstTab setView:firstView];

// 创建第二个 TabViewItem
NSTabViewItem *secondTab = [[NSTabViewItem alloc] initWithIdentifier:@"secondTab"];
[secondTab setLabel:@"Second Tab"];  // 设置标签页名称
NSView *secondView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 600, 400)];
[secondView setWantsLayer:YES];
[secondView.layer.backgroundColor = [NSColor blueColor].CGColor];
[secondTab setView:secondView];

// 将标签页添加到 TabView
[tabView addTabViewItem:firstTab];
[tabView addTabViewItem:secondTab];

Swift

// 创建第一个 TabViewItem
let firstTab = NSTabViewItem(identifier: "firstTab")
firstTab.label = "First Tab"  // 设置标签页名称
let firstView = NSView(frame: NSRect(x: 0, y: 0, width: 600, height: 400))
firstView.wantsLayer = true
firstView.layer?.backgroundColor = NSColor.red.cgColor
firstTab.view = firstView

// 创建第二个 TabViewItem
let secondTab = NSTabViewItem(identifier: "secondTab")
secondTab.label = "Second Tab"  // 设置标签页名称
let secondView = NSView(frame: NSRect(x: 0, y: 0, width: 600, height: 400))
secondView.wantsLayer = true
secondView.layer?.backgroundColor = NSColor.blue.cgColor
secondTab.view = secondView

// 将标签页添加到 TabView
tabView.addTabViewItem(firstTab)
tabView.addTabViewItem(secondTab)

数据源和委托

NSTabView 使用委托(NSTabViewDelegate)来处理标签页的选择和其他事件。

Objective-C

// 设置代理
[tabView setDelegate:self];
// 实现代理方法,当选择不同标签页时调用
- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(nullable NSTabViewItem *)tabViewItem {
    NSLog(@"Selected tab: %@", tabViewItem.label);  // 处理标签页选择事件
}

Swift

// 设置代理
tabView.delegate = self
// 实现代理方法,当选择不同标签页时调用
func tabView(_ tabView: NSTabView, didSelect tabViewItem: NSTabViewItem?) {
    if let tabViewItem = tabViewItem {
        print("Selected tab: \(tabViewItem.label)")  // 处理标签页选择事件
    }
}

使用自动布局

NSTabView 也支持自动布局,这使得调整窗口大小时标签页内容能够更好地适应变化。

Objective-C

// 使用自动布局进行初始化
NSView *firstView = [[NSView alloc] init];
NSView *secondView = [[NSView alloc] init];

[firstView setTranslatesAutoresizingMaskIntoConstraints:NO];  // 禁用自动转换约束
[secondView setTranslatesAutoresizingMaskIntoConstraints:NO];

[firstTab setView:firstView];
[secondTab setView:secondView];

[NSLayoutConstraint activateConstraints:@[
    [firstView.leadingAnchor constraintEqualToAnchor:tabView.leadingAnchor],
    [firstView.trailingAnchor constraintEqualToAnchor:tabView.trailingAnchor],
    [firstView.topAnchor constraintEqualToAnchor:tabView.topAnchor],
    [firstView.bottomAnchor constraintEqualToAnchor:tabView.bottomAnchor],
    
    [secondView.leadingAnchor constraintEqualToAnchor:tabView.leadingAnchor],
    [secondView.trailingAnchor constraintEqualToAnchor:tabView.trailingAnchor],
    [secondView.topAnchor constraintEqualToAnchor:tabView.topAnchor],
    [secondView.bottomAnchor constraintEqualToAnchor:tabView.bottomAnchor]
]];

Swift

// 使用自动布局进行初始化
let firstView = NSView()
let secondView = NSView()

firstView.translatesAutoresizingMaskIntoConstraints = false  // 禁用自动转换约束
secondView.translatesAutoresizingMaskIntoConstraints = false

firstTab.view = firstView
secondTab.view = secondView

NSLayoutConstraint.activate([
    firstView.leadingAnchor.constraint(equalTo: tabView.leadingAnchor),
    firstView.trailingAnchor.constraint(equalTo: tabView.trailingAnchor),
    firstView.topAnchor.constraint(equalTo: tabView.topAnchor),
    firstView.bottomAnchor.constraint(equalTo: tabView.bottomAnchor),
    
    secondView.leadingAnchor.constraint(equalTo: tabView.leadingAnchor),
    secondView.trailingAnchor.constraint(equalTo: tabView.trailingAnchor),
    secondView.topAnchor.constraint(equalTo: tabView.topAnchor),
    secondView.bottomAnchor.constraint(equalTo: tabView.bottomAnchor)
])

高级用法

动态增减标签页

Objective-C

添加标签页

NSTabViewItem *newTab = [[NSTabViewItem alloc] initWithIdentifier:@"newTab"];
[newTab setLabel:@"New Tab"];  // 设置新标签页名称
NSView *newView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 600, 400)];
[newView setWantsLayer:YES];
[newView.layer.backgroundColor = [NSColor greenColor].CGColor];
[newTab setView:newView];

// 动态添加到 TabView
[tabView addTabViewItem:newTab];

移除标签页

NSTabViewItem *tabToRemove = [tabView tabViewItemAtIndex:0];
[tabView removeTabViewItem:tabToRemove];

Swift

添加标签页

let newTab = NSTabViewItem(identifier: "newTab")
newTab.label = "New Tab"  // 设置新标签页名称
let newView = NSView(frame: NSRect(x: 0, y: 0, width: 600, height: 400))
newView.wantsLayer = true
newView.layer?.backgroundColor = NSColor.green.cgColor
newTab.view = newView

// 动态添加到 TabView
tabView.addTabViewItem(newTab)

移除标签页

if let tabToRemove = tabView.tabViewItem(at: 0) {
    tabView.removeTabViewItem(tabToRemove)
}

自定义标签

你可以通过自定义视图来替换 NSTabViewItem 的默认标题视图。

Objective-C

// 自定义标签视图
NSTabViewItem *customTab = [[NSTabViewItem alloc] initWithIdentifier:@"customTab"];
NSView *customLabelView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 30)];
NSTextField *customLabel = [[NSTextField alloc] initWithFrame:customLabelView.bounds];
[customLabel setStringValue:@"Custom Tab"];
[customLabel setBezeled:NO];
[customLabel setDrawsBackground:NO];
[customLabel setEditable:NO];
[customLabel setSelectable:NO];
[customLabelView addSubview:customLabel];
[customTab setLabelView:customLabelView];

// 创建内容视图
NSView *customView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 600, 400)];
[customView setWantsLayer:YES];
[customView.layer.backgroundColor = [NSColor yellowColor].CGColor];
[customTab setView:customView];

// 将自定义标签页添加到 TabView
[tabView addTabViewItem:customTab];

Swift

// 自定义标签视图
let customTab = NSTabViewItem(identifier: "customTab")
let customLabelView = NSView(frame: NSMakeRect(0, 0, 100, 30))
let customLabel = NSTextField(frame: customLabelView.bounds)
customLabel.stringValue = "Custom Tab"
customLabel.isBezeled = false
customLabel.drawsBackground = false
customLabel.isEditable = false
customLabel.isSelectable = false
customLabelView.addSubview(customLabel)
customTab.labelView = customLabelView

// 创建内容视图
let customView = NSView(frame: NSRect(x: 0, y: 0, width: 600, height: 400))
customView.wantsLayer = true
customView.layer?.backgroundColor = NSColor.yellow.cgColor
customTab.view = customView

// 将自定义标签页添加到 TabView
tabView.addTabViewItem(customTab)

切换标签页

你可以通过代码来控制标签页的切换。

Objective-C

// 选中第一个标签页
[tabView selectTabViewItemAtIndex:0];

// 选中特定标识符的标签页
NSTabViewItem *tabItem = [tabView tabViewItemAtIndex:0];
[tabView selectTabViewItem:tabItem];

Swift

// 选中第一个标签页
tabView.selectTabViewItem(at: 0)

// 选中特定标识符的标签页
if let tabItem = tabView.tabViewItem(at: 0) {
    tabView.selectTabViewItem(tabItem)
}

刷新标签视图

在某些情况下,您可能需要刷新标签视图的内容,例如在标签名称发生变化时。

Objective-C

- (void)refreshTabLabel:(NSTabViewItem *)tabItem newLabel:(NSString *)newLabel {
    [tabItem setLabel:newLabel];
    [tabView updateTabViewItems];  // 刷新标签视图
}

Swift

func refreshTabLabel(_ tabItem: NSTabViewItem, newLabel: String) {
    tabItem.label = newLabel
    tabView.updateTabViewItems()  // 刷新标签视图
}

封装工具类

为了更方便地使用 NSTabView,可以封装一个工具类,提供常见功能的高层接口。

Objective-C

#import <Cocoa/Cocoa.h>

@interface NSTabViewHelper : NSObject

+ (NSTabView *)createTabViewWithFrame:(NSRect)frame tabItems:(NSArray<NSDictionary<NSString *, NSView *> *> *)tabItems;
+ (void)addTabWithLabel:(NSString *)label toTabView:(NSTabView *)tabView withView:(NSView *)view;

@end

@implementation NSTabViewHelper

+ (NSTabView *)createTabViewWithFrame:(NSRect)frame tabItems:(NSArray<NSDictionary<NSString *, NSView *> *> *)tabItems {
    NSTabView *tabView = [[NSTabView alloc] initWithFrame:frame];
    for (NSDictionary<NSString *, NSView *> *item in tabItems) {
        NSString *label = item.allKeys.firstObject;
        NSView *view = item.allValues.firstObject;
        [NSTabViewHelper addTabWithLabel:label toTabView:tabView withView:view];
    }
    return tabView;
}

+ (void)addTabWithLabel:(NSString *)label toTabView:(NSTabView *)tabView withView:(NSView *)view {
    NSTabViewItem *tabItem = [[NSTabViewItem alloc] initWithIdentifier:label];
    [tabItem setLabel:label];
    [tabItem setView:view];
    [tabView addTabViewItem:tabItem];
}

@end

Swift

import Cocoa

class NSTabViewHelper {
    
    // 创建 TabView 并初始化标签项
    static func createTabView(frame: NSRect, tabItems: [String: NSView]) -> NSTabView {
        let tabView = NSTabView(frame: frame)
        for (label, view) in tabItems {
            addTab(withLabel: label, to: tabView, with: view)
        }
        return tabView
    }
    
    // 添加标签页
    static func addTab(withLabel label: String, to tabView: NSTabView, with view: NSView) {
        let tabItem = NSTabViewItem(identifier: label)
        tabItem.label = label
        tabItem.view = view
        tabView.addTabViewItem(tabItem)
    }
}

使用示例

Objective-C

// 创建 TabView
NSView *firstView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 600, 400)];
[firstView setWantsLayer:YES];
[firstView.layer setBackgroundColor:[NSColor redColor].CGColor];

NSView *secondView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 600, 400)];
[secondView setWantsLayer:YES];
[secondView.layer setBackgroundColor:[NSColor blueColor].CGColor];

NSTabView *tabView = [NSTabViewHelper createTabViewWithFrame:NSMakeRect(0, 0, 600, 400)
    tabItems:@[
        @{@"First Tab": firstView},
        @{@"Second Tab": secondView}
    ]];

Swift

// 创建 TabView
let firstView = NSView(frame: NSRect(x: 0, y: 0, width: 600, height: 400))
firstView.wantsLayer = true
firstView.layer?.backgroundColor = NSColor.red.cgColor

let secondView = NSView(frame: NSRect(x: 0, y: 0, width: 600, height: 400))
secondView.wantsLayer = true
secondView.layer?.backgroundColor = NSColor.blue.cgColor

let tabView = NSTabViewHelper.createTabView(frame: NSRect(x: 0, y: 0, width: 600, height: 400), tabItems: [
    "First Tab": firstView,
    "Second Tab": secondView
])

总结

通过了解 NSTabView 的基本使用、委托方法、动态增减标签页、自定义标签等高级用法,以及封装工具类,你将能够更高效地使用 NSTabView 创建复杂的选项卡界面。在实际应用中,合理使用这些技巧可以显著提升用户界面的灵活性和用户体验。

posted @ 2024-08-06 18:01  Mr.陳  阅读(26)  评论(0编辑  收藏  举报