Mac开发_NSPopover

1、基础创建

  • 1.1 代码

@property(nonatomic, strong) NSPopover *gc_popover;

@property(nonatomic, strong) Popover_Controller *gc_controller;

@property(nonatomic, assign) BOOL pop_on;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    NSButton *button = [[NSButton alloc] init];
    button.frame = NSMakeRect(150, 100, 60, 40);
    [self.window.contentView addSubview:button];
    // 添加点击事件
    button.target = self;
    button.action = @selector(button_Tap:);
}

- (void)button_Tap:(NSButton *)button {
    self.pop_on = !self.pop_on;
    if (self.pop_on) {
        // 具体参考坐标是多少,具体显示在哪里
        // NSRectEdgeMinY :显示在button 上面
        [self.gc_popover showRelativeToRect:[button bounds] ofView:button preferredEdge:NSRectEdgeMinX];
    }
    else {
        // 主动关闭显示
        [self.gc_popover close];
    }
    
    GCLog(@"popover是否在显示 == %@", @(self.gc_popover.isShown));
}

// 懒加载 popover
- (NSPopover *)gc_popover {
    if(!_gc_popover) {
        // 创建
        _gc_popover = [[NSPopover alloc] init];
        // Popover的代理对象,用于处理Popover的生命周期和用户事件。
        _gc_popover.delegate = self;
        
        // NSAppearanceNameAqua(默认)
        // NSAppearanceNameDarkAqua(深色)。
        NSAppearance *popoverAppearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
        // 设置popover的外观。
        _gc_popover.appearance = popoverAppearance;
        // Popover的当前有效外观,即在Popover中显示的所有控件的外观。
        // 该属性会受到系统主题、用户设置和Popover自身的属性等多个因素的影响。
        // 通过检查effectiveAppearance,可以确保Popover中的控件外观与当前系统和用户设置保持一致。
        NSAppearance *effectiveAppearance = _gc_popover.effectiveAppearance;
        GCLog(@"当前有效外观 == %@", effectiveAppearance.name);
        // popover的弹出收回管理方式,默认 NSPopoverBehaviorApplicationDefined,即点击空白处不会自动收回
        _gc_popover.behavior = NSPopoverBehaviorTransient;
        // Popover是否有动画效果。
        _gc_popover.animates = YES;
        // Popover的内容视图控制器。
        _gc_popover.contentViewController = self.gc_controller;
        // Popover的内容视图大小。
        _gc_popover.contentSize = NSMakeSize(300, 400);
        // Popover的定位矩形,用于指定Popover的位置。
        _gc_popover.positioningRect = NSMakeRect(20, 30, 200, 180);

        // 当NSPopoverDelegate的popoverShouldClose方法返回true时,会调用performClose方法来关闭NSPopover。
        // 这个方法应该在子类中查看调用
        //- (IBAction)performClose:(nullable id)sender;

        // NSPopoverWillShowNotification 表示popover即将显示的通知;
        // NSPopoverDidShowNotification 表示popover已经显示的通知;
        // NSPopoverWillCloseNotification 表示popover即将关闭的通知;
        // NSPopoverDidCloseNotification 表示popover已经关闭的通知。
    }
    return _gc_popover;
}

// 懒加载 内容控制器
- (Popover_Controller *)gc_controller {
    if(!_gc_controller) {
        _gc_controller = [[Popover_Controller alloc] init];
    }
    return _gc_controller;
}
  • 1.2 代理

#pragma mark - NSPopoverDelegate
// Popover即将关闭时,此方法将被调用。
// 返回YES表示可以关闭,返回NO表示不可以关闭。
- (BOOL)popoverShouldClose:(NSPopover *)popover {
    return NO;
}

// 当Popover即将分离时,此方法将被调用。
// 返回YES表示可以分离,返回NO表示不可以分离。
- (BOOL)popoverShouldDetach:(NSPopover *)popover {
    return YES;
}

// 当Popover已经成功地被分离时,此方法将被调用。
// 可以在此方法中执行一些操作,比如更新UI。
- (void)popoverDidDetach:(NSPopover *)popover {

}

// 当Popover需要被分离时,此方法将被调用。
// 返回一个NSWindow对象,用于显示Popover的内容。如果返回nil,则Popover将使用默认的Window来显示内容。
- (nullable NSWindow *)detachableWindowForPopover:(NSPopover *)popover {
    return nil;
}
  • 1.3 代理式通知

// 当弹出窗口即将显示时调用该方法。
- (void)popoverWillShow:(NSNotification *)notification {

}

// 当弹出窗口已经显示时调用该方法。
- (void)popoverDidShow:(NSNotification *)notification {

}

// 当弹出窗口即将关闭时调用该方法。
- (void)popoverWillClose:(NSNotification *)notification {

}

// 当弹出窗口已经关闭时调用该方法。
- (void)popoverDidClose:(NSNotification *)notification {

}
  • 1.4 效果

2、其他

  • 2.1 Popover_Controller.h

    #import <Cocoa/Cocoa.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface Popover_Controller : NSViewController
    
    @end
    
    NS_ASSUME_NONNULL_END
    
  • 2.1 Popover_Controller.m

    #import "Popover_Controller.h"
    
    @interface Popover_Controller ()
    
    @end
    
    @implementation Popover_Controller
    
    // 这个一定要写,否则无法显示出来
    - (void)loadView {
        NSRect frame = [[[NSApplication sharedApplication] mainWindow] frame];
        self.view = [[NSView alloc] initWithFrame:frame];
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.view.wantsLayer = YES;
        self.view.layer.backgroundColor = [NSColor blueColor].CGColor;
    }
    
    @end
    
posted @ 2022-09-17 19:59  CH520  阅读(62)  评论(0编辑  收藏  举报