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;
}
#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;
}
// 当弹出窗口即将显示时调用该方法。
- (void)popoverWillShow:(NSNotification *)notification {
}
// 当弹出窗口已经显示时调用该方法。
- (void)popoverDidShow:(NSNotification *)notification {
}
// 当弹出窗口即将关闭时调用该方法。
- (void)popoverWillClose:(NSNotification *)notification {
}
// 当弹出窗口已经关闭时调用该方法。
- (void)popoverDidClose:(NSNotification *)notification {
}
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