如何使用NSVisualEffectView创建一个平滑,圆润,类似卷的OS X窗口? [英] How to make a smooth, rounded, volume-like OS X window with NSVisualEffectView?

查看:1343
本文介绍了如何使用NSVisualEffectView创建一个平滑,圆润,类似卷的OS X窗口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试创建一个类似于Volume OS X窗口的窗口:

I'm currently trying to make a window that looks like the Volume OS X window:


为此,我有自己的 NSWindow 一个自定义子类),它是透明的/无标题栏/无阴影的,在其contentView内有一个 NSVisualEffectView 。这里是我的子类的代码,使内容视图轮:


To make this, I have my own NSWindow (using a custom subclass), which is transparent/titlebar-less/shadow-less, that has a NSVisualEffectView inside its contentView. Here's the code of my subclass to make the content view round:

- (void)setContentView:(NSView *)aView {
   aView.wantsLayer            = YES;
   aView.layer.frame           = aView.frame;
   aView.layer.cornerRadius    = 14.0;
   aView.layer.masksToBounds   = YES;

   [super setContentView:aView];
}



这里是结果,角落是粒状的,OS X的方式更平滑):




任何想法如何使角落更流畅?感谢


And here's the outcome (as you can see, the corners are grainy, OS X's are way smoother):

Any ideas on how to make the corners smoother? Thanks

推荐答案

更新OS X El Capitan



描述在我原来的答案下面不再需要OS X El Capitan了。 NSVisualEffectView maskImage 应该正常工作,如果 NSWindow contentView 设置为 NSVisualEffectView (这是不够的,如果它是< c $ c> contentView )。

Update for OS X El Capitan

The hack I described in my original answer below is not needed on OS X El Capitan anymore. The NSVisualEffectView’s maskImage should work correctly there, if the NSWindow’s contentView is set to be the NSVisualEffectView (it’s not enough if it is a subview of the contentView).

以下是示例项目: https://github.com/marcomasser/OverlayTest

我找到了一种方法来覆盖一个私有的NSWindow方法: - (NSImage *)_ cornerMask 。只需返回一个通过绘制一个带有圆角矩形的NSBezierPath创建的图像,看起来类似于OS X的卷窗口。

I found a way to do this by overriding a private NSWindow method: - (NSImage *)_cornerMask. Simply return an image created by drawing an NSBezierPath with a rounded rect in it to get a look similar to OS X’s volume window.

在我的测试中,我发现您需要为NSVisualEffectView NSWindow使用掩码图片。在您的代码中,您使用视图的图层的 cornerRadius 属性获取圆角,但您可以通过使用蒙版图片实现相同。在我的代码中,我生成一个NSImage由NSVisualEffectView和NSWindow使用:

In my testing I found that you need to use a mask image for the NSVisualEffectView and the NSWindow. In your code, you’re using the view’s layer’s cornerRadius property to get the rounded corners, but you can achieve the same by using a mask image. In my code, I generate an NSImage that is used by both the NSVisualEffectView and the NSWindow:

func maskImage(#cornerRadius: CGFloat) -> NSImage {
    let edgeLength = 2.0 * cornerRadius + 1.0
    let maskImage = NSImage(size: NSSize(width: edgeLength, height: edgeLength), flipped: false) { rect in
        let bezierPath = NSBezierPath(roundedRect: rect, xRadius: cornerRadius, yRadius: cornerRadius)
        NSColor.blackColor().set()
        bezierPath.fill()
        return true
    }
    maskImage.capInsets = NSEdgeInsets(top: cornerRadius, left: cornerRadius, bottom: cornerRadius, right: cornerRadius)
    maskImage.resizingMode = .Stretch
    return maskImage
}

然后我创建了一个NSWindow子类,它有一个setter用于遮罩图像:

I then created an NSWindow subclass that has a setter for the mask image:

class MaskedWindow : NSWindow {

    /// Just in case Apple decides to make `_cornerMask` public and remove the underscore prefix,
    /// we name the property `cornerMask`.
    @objc dynamic var cornerMask: NSImage?

    /// This private method is called by AppKit and should return a mask image that is used to 
    /// specify which parts of the window are transparent. This works much better than letting 
    /// the window figure it out by itself using the content view's shape because the latter
    /// method makes rounded corners appear jagged while using `_cornerMask` respects any
    /// anti-aliasing in the mask image.
    @objc dynamic func _cornerMask() -> NSImage? {
        return cornerMask
    }

}

然后,在我的NSWindowController子类中,我为视图和窗口设置了掩码图像:

Then, in my NSWindowController subclass I set up the mask image for the view and the window:

class OverlayWindowController : NSWindowController {

    @IBOutlet weak var visualEffectView: NSVisualEffectView!

    override func windowDidLoad() {
        super.windowDidLoad()

        let maskImage = maskImage(cornerRadius: 18.0)
        visualEffectView.maskImage = maskImage
        if let window = window as? MaskedWindow {
            window.cornerMask = maskImage
        }
    }
}

这篇关于如何使用NSVisualEffectView创建一个平滑,圆润,类似卷的OS X窗口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆