I haven’t updated my article for nearly a month, but I started working on it again today, haha. Recently, Tencent finally released the MAC end of Tencent Video on May 12. The opened Tencent Video members can finally be used on the MAC. Ordinary use webpage to see member video not quite habit, still like client end. Have to say, Tencent video MAC end personal feeling do very good, the details are also very in place.

Two days ago to know Tencent video MAC terminal release, immediately downloaded down to use the next. There is a new function: when the mouse moves over the video introduction, a small preview window will pop up gently. This function has never been encountered on MAC before, I am very happy and I feel creative. The function is shown in the red box in the picture below.





QQ20170516-173448.png

So I tried it out on my own to see how it could be done, and finally implemented it before I left work.

The first:





11.gif

The second:





float.gif

The third:





2.gif

Just to give you an idea, the first thing that came to mind was to do this with a singleton, and then create a method that inherits from NSObject that implements a singleton method, and then add a method to the class that creates a custom NSMenu, which pops up, but it doesn’t work very well. The custom NSMenu is replaced with NSWindow, which finally implements this functionality.

1. Create a singleton

This is an easy step to skip.

2. Create a custom NSWindow

@interface ShareMenu(a)
@property (nonatomic.strong) NSWindow *subWindow;

@end
@implementation ShareMenu

static ShareMenu *menu = nil; + (instancetype)share{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        menu = [[self alloc]init];
    });
    return menu;
}
- (instancetype)init
{
    self = [super init];
    if (self) {
        _edgeOffset = 10;
    }
    return self; } - (void)setEdgeOffset:(CGFloat)edgeOffset{ _edgeOffset = edgeOffset; } - (NSWindow *)subWindow{
    if(! _subWindow) { _subWindow = [[NSWindow alloc]init];
        _subWindow.styleMask = NSWindowStyleMaskFullSizeContentView|NSWindowStyleMaskTitled;
        _subWindow.backingType = NSBackingStoreNonretained;
        _subWindow.titlebarAppearsTransparent = YES;
        _subWindow.titleVisibility = NSWindowTitleHidden;

    }
    return _subWindow;
}Copy the code

I prefer to use lazy loading to add controls to prevent multiple creation problems.

2. Add object methods in ShareMenu

-(void)popOverMenuWithItem:(NSCollectionViewItem *)item {// convertItem location on the left in the contentView NSRect the rect = [item. View. Window. ContentView convertRect:item.view.frame fromView:item.collectionView];
    [self.subWindow setFrame:NSMakeRect(item.view.window.frame.origin.x
                                        + item.view.frame.origin.x
                                        - _edgeOffset
                                        ,item.view.window.frame.origin.y
                                        + rect.origin.y
                                        - _edgeOffset
                                        , item.view.bounds.size.width
                                        + _edgeOffset * 2
                                        , item.view.bounds.size.height
                                        + _edgeOffset * 2) display:YES];
    //------------------------------------------------------------------- / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- create contentView here -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - / / / / NSView instance 1 * redView = [[NSView alloc]initWithFrame:NSMakeRect(0, 0, 0, 0)];
//    redView.wantsLayer = YES; // redView.layer.backgroundColor = [NSColor redColor].CGColor; / / redView. Animator. AlphaValue = 0.3; // self.subWindow.contentView = redView; NSView *backgroundView = [[NSView alloc]init]; backgroundView.wantsLayer = YES; backgroundView.layer.backgroundColor = [NSColor whiteColor].CGColor; NSView *tmpView = [[[NSStoryboard storyboardWithName:@"Main" bundle:nil]instantiateControllerWithIdentifier:@"copyItem"] view];
    TmpView. Animator. AlphaValue = 0.3; tmpView.layer.cornerRadius = 5; self.subWindow.contentView = backgroundView; [backgroundView addSubview:tmpView];

    //------------------------------------------------------------------- [NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull context) {
        context.duration = kDuration;
        context.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
//        RedView. Animator. AlphaValue = 0.99; TmpView. Animator. AlphaValue = 0.8; [NSApp.keyWindow.animator addChildWindow:self.subWindow ordered:NSWindowAbove];
    } completionHandler:nil];

}Copy the code

The core code is inside this -(void)popOverMenuWithItem:(NSCollectionViewItem *)item.

3. Add a closing method, that is, remove the pop-up

/ / close- (void)close{
    if (_subWindow) {
        [NSApp.keyWindow removeChildWindow:self.subWindow];
        self.subWindow = nil; }}Copy the code

4. Use of ShareMenu





QQ20170516-180208.png

Add NSTrackingArea to custom NSCollectionViewItem and call the -(void)mouseEntered:(NSEvent *)event method as shown above, in case the window might stretch, Add the code shown in the figure to the notification that also adds window changes.

Close the popover while sliding, as shown below





QQ20170516-180556.png

Finally, if you want to see the source code, please go to my GitHub to find it

github.com/shibiao