欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Mac开发之NSWindow自定义titlebar实现

程序员文章站 2022-07-14 10:09:51
...

Mac开发之NSWindow自定义titlebar实现

其中使用到了布局框架:Masonry

1. tab按钮实现

#import <Cocoa/Cocoa.h>

@interface ZLTabView : NSView

// 回调到主控制器
@property (nonatomic, copy) void(^TabSelect)(NSInteger sender);

// 外部调用选中第几个按钮 0、1、2、……
- (void)select:(NSInteger)index;

@end

#import "ZLTabView.h"

@interface ZLTabView()

// 记录当前选中按钮,方便状态切换
@property (nonatomic, weak) NSButton *curButton;

@end

@implementation ZLTabView

- (instancetype)init {

    if(self = [super init]) {

        [[NSBundle mainBundle] loadNibNamed:@"ZLTabView" owner:self topLevelObjects:nil];

        NSNib *cnib = [[NSNib alloc] initWithNibNamed:@"ZLTabView" bundle:nil];

        NSArray *viewsArray = [[NSArray alloc] init];
        [cnib instantiateWithOwner:nil topLevelObjects:&viewsArray];

        for (int i = 0; i < viewsArray.count; i++) {
            if ([viewsArray[i] isKindOfClass:[ZLTabView class]]) {
                self = viewsArray[i];
                _curButton = self.subviews.firstObject;
                break;
            }
        }
    }
    return self;
}

- (void)select:(NSInteger)index {
    [self courseIntroClick:self.subviews.firstObject];
}

- (IBAction)courseIntroClick:(NSButton *)sender {
    NSLog(@"clicked %d", sender.state);
    self.curButton.state = !self.curButton.state;
    self.curButton = sender;
    self.TabSelect(sender.tag-9);  // 我设置的button的tag从9开始
}

@end

xib文件如图所示:

Mac开发之NSWindow自定义titlebar实现

2. window的titlebar布局调整

// 遵守<NSWindowDelegate>协议

// 隐藏标题
self.window.titleVisibility = NSWindowTitleHidden;

// 在恰当的地方添加顶部tab按钮
[[self.window standardWindowButton:NSWindowCloseButton].superview addSubview:self.tabview];


// 根据是否全屏刷新布局
- (void)windowResizeAction:(BOOL)fullscreen{

    // 获取titlebar视图
    NSView *titleBarContainerView = [self.window standardWindowButton:NSWindowCloseButton].superview.superview;
    [titleBarContainerView mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(@0);
        make.right.equalTo(@0);
        make.top.equalTo(@0);
        if (fullscreen) {
            make.height.equalTo(@22);
        } else {
            make.height.mas_equalTo(ZLTitlebarHeight);
        }
    }];

    // 关闭、最小化等按钮
    NSButton *closeBtn = [self.window standardWindowButton:NSWindowCloseButton];
    NSButton *zoomBtn = [self.window standardWindowButton:NSWindowZoomButton];
    NSButton *minBtn = [self.window standardWindowButton:NSWindowMiniaturizeButton];


    for (NSView *buttonView in @[closeBtn, zoomBtn, minBtn]) {
        [buttonView mas_remakeConstraints:^(MASConstraintMaker *make) {
            if (fullscreen) {
                make.top.mas_equalTo(3.0);
            } else {
                make.centerY.mas_equalTo(buttonView.superview.mas_centerY);
            }
        }];
    }
}

#pragma mark - WindowDelegate Methods
- (void)windowDidEnterFullScreen:(NSNotification *)notification {
    [self windowResizeAction:true];
}
- (void)windowDidExitFullScreen:(NSNotification *)notification {
    [self windowResizeAction:false];
}
- (void)windowDidResize:(NSNotification *)notification {
    [self windowResizeAction:false];
}

3. tabview的使用

self.tabview = [[ZLTabView alloc] init];
__weak typeof(self) weakSelf = self;
self.tabview.TabSelect = ^(NSInteger sender) {
    NSLog(@"%d", sender);
    if (sender==0) {

        // 这里切换控制器
        weakSelf.window.contentViewController = firstVC;

    } else if(sender==1) {


    } else {

    }
};

// 将tabview添加到titlebar上
[[self.window standardWindowButton:NSWindowCloseButton].superview addSubview:self.tabview];
// 设置默认选中项
[self.tabview select:0];

// 设置tabview的位置
[self.tabview mas_updateConstraints:^(MASConstraintMaker *make) {
    make.size.mas_equalTo(NSMakeSize(260, 40));
    make.centerX.mas_equalTo(self.tabview.superview.mas_centerX);
    make.centerY.mas_equalTo(self.tabview.superview.mas_centerY);
}];