【问题标题】:Custom NSWindow with rounded corners which clip subviews带有圆角的自定义 NSWindow 可以剪切子视图
【发布时间】:2013-02-17 05:26:17
【问题描述】:

我正在尝试创建一个自定义NSWindow,因此我创建了一个具有正确无边框窗口掩码的并且可以正常工作。我提供了我自己的内容视图,这很好。但我想做的是用圆角绘制将子视图剪辑到这些角。这可能吗?

在我的内容视图中,我可以覆盖 drawRect: 并绘制圆角路径,但是当我向其中添加子视图时,它们不会被剪裁。

我可以改为让我的内容视图有图层支持并给它一个圆角半径(masksToBounds 设置为YES)但是当我添加子视图时,它们仍然没有被我的圆角剪裁。

有没有办法做到这一点?或者以某种方式绘制没有标题栏的 NSWindow 并且我可以完全控制绘图,同时保持圆角的剪裁角?

【问题讨论】:

    标签: cocoa calayer nswindow


    【解决方案1】:

    我能够做的是提供我的 NSWindow 的自定义子类:

    @implementation ELGRoundWindow
    
    - (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
    {
        self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:bufferingType defer:flag];
    
        if ( self )
        {
            [self setStyleMask:NSBorderlessWindowMask];
            [self setOpaque:NO];
            [self setBackgroundColor:[NSColor clearColor]];
        }
    
        return self;
    }
    
    
    - (void) setContentView:(NSView *)aView
    {
        aView.wantsLayer            = YES;
        aView.layer.frame           = aView.frame;
        aView.layer.cornerRadius    = 20.0;
        aView.layer.masksToBounds   = YES;
    
    
        [super setContentView:aView];
    
    }
    
    @end
    

    然后在 IB 中,我将内容视图的类更改为 ELGRroundView:

    @implementation ELGRoundView
    
    - (void)drawRect:(NSRect)dirtyRect
    {
        [[NSColor colorWithCalibratedRed:0.0 green:0.5 blue:1 alpha:1] set];
        NSRectFill(dirtyRect);
    }
    
    @end
    

    我在内容视图中放置了另一个方形子视图,内容如下:

    @implementation ELGSquareView
    
    - (void)drawRect:(NSRect)dirtyRect
    {
        [[NSColor colorWithCalibratedRed:0.0 green:0 blue:1 alpha:1] set];
        NSRectFill(dirtyRect);
    }
    
    @end
    

    我最终得到:

    【讨论】:

    • 其他读者应该注意,OpenGL 应用程序应该只对整个场景使用一个glDrawArrays() 命令,否则图层会导致奇怪的结果。在这个问题的范围内,对 OS X 风格的角使用 4.5-5.0 的角半径。如果你愿意,你也可以保留正常的标题栏,而不会让它看起来太不一样。
    • @ericgorr 知道如何对此有所了解吗?
    【解决方案2】:

    @ericgorr 的建议是正确的。此外,如果您希望窗口可移动且可调整大小,请按如下方式更改 NSWindow 的 init,

    - (id)initWithContentRect:(NSRect)contentRect
                     styleMask:(NSUInteger)aStyle
                       backing:(NSBackingStoreType)bufferingType
                         defer:(BOOL)flag
    {
        self = [super initWithContentRect:contentRect
                                styleMask:aStyle
                                  backing:bufferingType
                                    defer:flag];
        if (self) {            
            [self setOpaque:NO];
            [self setBackgroundColor:[NSColor clearColor]];
            [self setMovableByWindowBackground:YES];
            [self setStyleMask:NSResizableWindowMask];
        }
        return self;
    }
    

    更多定制请参考Apple sample codehttp://developer.apple.com/library/mac/#samplecode/RoundTransparentWindow/Introduction/Intro.html

    【讨论】:

      【解决方案3】:

      子类化是最灵活的方式。 如果您不想子类化,请使用此代码。

      // unfortunately the window can't be moved
      // but this is just an alert type window, so i don't care
      //
      [window setOpaque:NO];
      [window setBackgroundColor:[NSColor clearColor]];
      
      NSView*  contentView = window.contentView;
      
      contentView.wantsLayer = YES;
      contentView.layer.backgroundColor = [NSColor windowBackgroundColor].CGColor;
      contentView.layer.masksToBounds = YES;
      contentView.layer.cornerRadius = 16.0;
      
      [window makeKeyAndOrderFront:self];
      [window center];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-22
        • 2011-12-23
        • 2019-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-16
        相关资源
        最近更新 更多