macOS 实现腾讯视频mac端卡片式预览小窗口

快一个月的时间没有更新文章,今天又开始操刀,哈哈。最近腾讯终于在5月12号发布了腾讯视频mac端,开通的腾讯视频会员终于在mac上可以派上用场。平常用网页看会员视频不太习惯,还是喜欢客户端。不得不说,腾讯视频mac端个人感觉做的挺好,细节做的也很到位。

前两天才知道腾讯视频mac端的发布,立马下载下来使用了下。有一功能感觉很新鲜:当鼠标移动在视频简介上的时候,轻轻弹出预览小窗口,这个功能之前mac上没碰到过,很欣喜,感觉有创意,功能如下图红色方框所示。

macOS 实现腾讯视频mac端卡片式预览小窗口
QQ20170516-173448.png

于是自己试了试看怎样才能实现,终于在下班前实现了此功能。

第一种:

macOS 实现腾讯视频mac端卡片式预览小窗口
11.gif

第二种:

macOS 实现腾讯视频mac端卡片式预览小窗口
float.gif

第三种:

macOS 实现腾讯视频mac端卡片式预览小窗口
2.gif

说一下我的思路,在脑海中第一闪现的是通过单例实现此功能,然后通过创建一个继承于NSObject类,通过此类实现单例方法,在类中添加了一个创建自定义NSMenu的方法,来实现弹出的小方框,通过自定义NSMenu虽然能弹出,但效果很差。于是将自定义NSMenu替换成NSWindow,终于实现了此功能。

1.创建单例

这一步很简单,略过。

2.创建自定义NSWindow

@interface ShareMenu ()
@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;
}

个人比较喜欢用懒加载添加控件,防止出现多次创建的问题。

2.在ShareMenu中添加对象方法

-(void)popOverMenuWithItem:(NSCollectionViewItem *)item {
    //转换item在contentView中的左边位置
    NSRect 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];
    //-------------------------------------------------------------------
    //-------------------------在此处创建contentView----------------------
    //实例1
//    NSView *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;
    //实例2
    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];

}

核心代码都在这个 -(void)popOverMenuWithItem:(NSCollectionViewItem *)item里面。

3.添加关闭方法,就是移除弹出框

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

4. ShareMenu的使用

macOS 实现腾讯视频mac端卡片式预览小窗口
QQ20170516-180208.png

在自定义NSCollectionViewItem中添加NSTrackingArea,并在-(void)mouseEntered:(NSEvent *)event方法调用如上图所示方法,因为考虑到窗口可能会拉伸,还要加窗口改变的通知里添加如图所示代码。

当滑动的时候关闭弹窗,代码如下图所示

macOS 实现腾讯视频mac端卡片式预览小窗口
QQ20170516-180556.png

最后,如果大家想看源码,请进我的GitHub里找寻

https://github.com/shibiao

-原文链接-