30

以下の「Xcodeへようこそ」ウィンドウのように、角が丸く影のあるタイトルバーNSWindowなし( )を作成しようとしています。NSBorderlessWindowMask

Xcode へようこそ

私はのサブクラスを作りますNSWindow:

@implementation FlatWindow

- (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 setOpaque:NO];
        [self setBackgroundColor:[NSColor clearColor]];
        [self setMovableByWindowBackground:TRUE];
        [self setStyleMask:NSBorderlessWindowMask];
        [self setHasShadow:YES];
    }

    return self;
}

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

    [super setContentView:aView];
}

@end

そしてのサブクラスNSView

@implementation ColoredView

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    [[NSColor windowBackgroundColor] set];
    NSRectFill(dirtyRect);
}

@end

これにより、角が丸いタイトルバーのないウィンドウが表示されますが、デフォルトのシャドウNSWindowはなくなりました。このウィンドウにデフォルトの影を追加するにはどうすればよいですか?

フラットウィンドウ

EDIT1:

NSWindow とNSShadow. この影は表示されません。

@implementation FlatWindow

- (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 setOpaque:NO];
        [self setBackgroundColor:[NSColor clearColor]];
        [self setMovableByWindowBackground:TRUE];
        [self setStyleMask:NSBorderlessWindowMask];
        [self setHasShadow:YES];
    }

    return self;
}

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

    NSShadow *dropShadow = [[NSShadow alloc] init];
    [dropShadow setShadowColor:[NSColor blackColor]];
    [dropShadow setShadowBlurRadius:10.0];
    [aView setShadow: dropShadow];

    [super setContentView:aView];
}

@end
4

11 に答える 11

21

アップデート

これまでのアプローチでは、正確なラウンド コーナーを作成できないことに気付きました。そこで、例を更新して正確な角を丸くしました。

ここに画像の説明を入力

        window1.backgroundColor             =   NSColor.whiteColor()
        window1.opaque                      =   false
        window1.styleMask                   =   NSResizableWindowMask
                                            |   NSTitledWindowMask
                                            |   NSFullSizeContentViewWindowMask
        window1.movableByWindowBackground   =   true
        window1.titlebarAppearsTransparent  =   true
        window1.titleVisibility             =   .Hidden
        window1.showsToolbarButton          =   false
        window1.standardWindowButton(NSWindowButton.FullScreenButton)?.hidden   =   true
        window1.standardWindowButton(NSWindowButton.MiniaturizeButton)?.hidden  =   true
        window1.standardWindowButton(NSWindowButton.CloseButton)?.hidden        =   true
        window1.standardWindowButton(NSWindowButton.ZoomButton)?.hidden         =   true

        window1.setFrame(CGRect(x: 400, y: 0, width: 400, height: 500), display: true)
        window1.makeKeyAndOrderFront(self)

完全な動作例を次に示します


古い

少なくとも OS X 10.10 では特別な処理は必要ありません。

import Cocoa

class ExampleApplicationController: NSObject, NSApplicationDelegate {
    class ExampleController {

        let window1 =   NSWindow()
        let view1   =   NSView()

        init(){
            window1.setFrame(CGRect(x: 400, y: 0, width: 400, height: 500), display: true)
            window1.contentView                 =   view1

            window1.backgroundColor             =   NSColor.clearColor()
            window1.opaque                      =   false
            window1.styleMask                   =   NSBorderlessWindowMask | NSResizableWindowMask
            window1.movableByWindowBackground   =   true
            window1.makeKeyAndOrderFront(self)

            view1.wantsLayer                =   true
            view1.layer!.cornerRadius       =   10
            view1.layer!.backgroundColor    =   NSColor.whiteColor().CGColor

            /// :ref:   http://stackoverflow.com/questions/19940019/nswindow-with-round-corners-and-shadow/27613308#21247949
            window1.invalidateShadow()  //  This manual invalidation is REQUIRED because shadow generation is an expensive operation.
        }
    }

    let example1    =   ExampleController()
}

ここから実例をダウンロードできます。

于 2014-12-23T02:35:23.317 に答える
4

@Eonil回答の目的 C の例:

[window setBackgroundColor:[NSColor whiteColor]];
[window setOpaque:NO];
[window setStyleMask:NSResizableWindowMask | NSTitledWindowMask | NSFullSizeContentViewWindowMask];
[window setMovableByWindowBackground:YES];
[window setTitlebarAppearsTransparent:YES];
[window setTitleVisibility:NSWindowTitleHidden];
[window setShowsToolbarButton:NO];
[window standardWindowButton:NSWindowFullScreenButton].hidden = YES;
[window standardWindowButton:NSWindowMiniaturizeButton].hidden = YES;
[window standardWindowButton:NSWindowCloseButton].hidden = YES;
[window standardWindowButton:NSWindowZoomButton].hidden = YES;
[window makeKeyWindow];
于 2016-05-24T16:18:11.167 に答える
3

その際に役立つサンプル アプリケーションがApple Developer Siteにあります。このサンプルでは、​​カスタム形状、タイトル バーなし、および透明なコンテンツを持つウィンドウを作成する方法を示します。また、ウィンドウの形状を変更し、ウィンドウの境界のドロップ シャドウを再計算する方法も示します。

于 2013-11-13T09:11:06.967 に答える
3

最近使用したファイルのリスト ビューを含め、アプリケーション用に独自のバージョンの Xcode スプラッシュ スクリーンを作成したところ、四隅すべてが丸くなっています。

http://www.fizzypopstudios.com/splash.png

これを行う最も簡単な方法は、インターフェイス ビルダーを使用してウィンドウを作成することでした。ウィンドウを 800x470 ピクセルにしてから、"Shadow" と "Restorable" 以外のすべてのオプションのチェックを外しました。これにより、スプラッシュ スクリーンを作成する白紙の状態が残りました。

スプラッシュ ウィンドウのinitWithContentRect:styleMask:backing:defer:メソッドでは、次のプロパティも設定します。

self.opaque = NO
self.backgroundColor = [NSColor clearColor]
self.movableByWindowBackground = YES

この時点でウィンドウを表示すると、背景がなくなり、ウィンドウの影がウィンドウ内の透明でないコントロールの背後に自動的に設定されます。

ウィンドウの背景を描画するとき、左側の 500 ピクセルをライト グレーで塗りつぶし、右側の残りの 300 ピクセルを白で塗りつぶします。表示された場合、この時点でウィンドウの角は丸くなりません。

次に[NSColor clearColor]、ウィンドウの 4 つの角すべてに正方形を切り込みます (正方形のサイズは、次に描画する丸みを帯びた角の半径です)。次に、ベジエ パスを使用して、切り取ったノッチに丸みを帯びた角を描きます。

塗りつぶすと角が丸くなるベジエパスを作成してこれを実行しようとしましたが[NSColor clearColor]、何らかの理由でパスは他の色で塗りつぶされますが、クリアで塗りつぶされませんでした。

ここで、ウィンドウをレンダリングすると角が丸くなりますが、テーブル ビューをウィンドウの右側にドロップすると、角が再び正方形になります。簡単な解決策はNSScrollView、 を背景を描画しないように設定してから、ネストされたNSTableView背景を透明に設定することです。

テーブルの後ろに背景を描画しているので、背景を描画するテーブルやスクロール ビューは実際には必要ありません。これにより、丸みを帯びた角が保持されます。

4 つの角の近くに他のコントロールがある場合は、丸みを帯びた領域に入らないように十分にインデントしておいてください。この例は、ウィンドウの左下にボタンがありますが、ボタンには透明性があるため、丸みを帯びた角は削除されません。

もう1つの考慮事項は、これらのタイプのウィンドウのデフォルトとして返すウィンドウサブクラスのcanBecomeKeyWindowおよびメソッドを提供したい場合があることです。canBecomeMainWindowYESNO

この情報がウィンドウの作成に役立つことを願っています。少し前にあなたの質問を見て、私がどのようにウィンドウを作成したかをお知らせしたいと思いました。:)

于 2014-01-26T00:45:17.053 に答える
2

Apple Developer Documentation が完全に指摘しているように:

レイヤーに影を追加すると、影はレイヤーのコンテンツの一部になりますが、実際にはレイヤーの境界四角形の外側に広がります。その結果、レイヤーの maskToBounds プロパティを有効にすると、影の効果がエッジの周りでクリップされます。レイヤーに透明なコンテンツが含まれていると、レイヤーの直下の影の部分がまだ表示されているが、レイヤーを超えて伸びている部分が表示されないという奇妙な効果が生じる可能性があります。シャドウだけでなく境界マスキングも使用する場合は、1 つではなく 2 つのレイヤーを使用します。コンテンツを含むレイヤーにマスクを適用し、影効果が有効になっているまったく同じサイズの 2 番目のレイヤー内にそのレイヤーを埋め込みます。

記事全文: https://developer.apple.com/library/mac/documentation/cocoa/conceptual/coreanimation_guide/SettingUpLayerObjects/SettingUpLayerObjects.html#//apple_ref/doc/uid/TP40004514-CH13-SW12

したがって、実際には2つのビュー/レイヤーで作業する必要があります:

- (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 setOpaque:NO];
    [self setBackgroundColor:[NSColor clearColor]];
    [self setMovableByWindowBackground:TRUE];
    [self setStyleMask:NSBorderlessWindowMask];
    [self setHasShadow:YES];
}

return self;
}

- (BOOL)canBecomeKeyWindow {
return YES;
}

-(BOOL)canBecomeMainWindow {
return YES;
}

- (void) setContentView:(NSView *)aView {

NSView *backView = [[NSView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
backView.wantsLayer             = YES;
backView.layer.masksToBounds    = NO;
backView.layer.shadowColor      = [NSColor shadowColor].CGColor;
backView.layer.shadowOpacity    = 0.5;
backView.layer.shadowOffset     = CGSizeMake(0, -3);
backView.layer.shadowRadius     = 5.0;
backView.layer.shouldRasterize  = YES;


NSView *frontView = [aView initWithFrame:CGRectMake(backView.frame.origin.x + 15, backView.frame.origin.y + 15, backView.frame.size.width - 30, backView.frame.size.height - 30)];
[backView addSubview: frontView];
frontView.layer.cornerRadius    = 8;
frontView.layer.masksToBounds   = YES;
frontView.layer.borderColor     = [[NSColor darkGrayColor] CGColor];
frontView.layer.borderWidth     = 0.5;

[super setContentView:backView];

}

コードの「initWithFrame」部分を詳しく見てください。オーストリアのチロルからよろしくお願いします!

于 2014-01-25T20:52:31.207 に答える
1

あなたは私が抱えていたのと同じ問題に苦しんでいますが、良いニュースは、それを機能させるためのかなり簡単な方法を見つけたことです.

というわけで、概念的には、Xcode のウェルカム画面を見ると、ほとんど通常のウィンドウのように見えますが、タイトル バーはありません (そうですか? )。

ウィンドウ設定

私が行ったことは、通常のウィンドウを取得し、それを選択して属性インスペクターに移動し、タイトルバーの3つのボタンである「閉じる」、「最小化」、「サイズ変更」ボタンを無効にしました.

したがって、「裸の」ウィンドウが表示されますが、タイトル バーは表示されたままです。できることは、awakeFromNib デリゲートに次のコードを追加することです。

[self.window setTitle:@""];

ウィンドウがヘッダー ファイルのように宣言されていると仮定します。

@property (assign) IBOutlet NSWindow *window;

これで、完全に裸のタイトル バーができました。できることは、最終的な微調整です。

これは、awakeFromNib デリゲートでも実行できます。

[self.window setBackgroundColor: [NSColor colorWithCalibratedWhite:0.97 alpha:1.0]];

閉じるボタン

次の方法を使用しました: ボタンまたはビューを NSWindow タイトル バーに追加する

だから私はただ使うことができます(私はawakeFromNibデリゲートでもそれをしました):

//Creating the button:
NSButton *closeButton = [[NSButton alloc] initWithFrame:NSMakeRect(0,0,12,12)];
NSButtonCell *closeButtonCell = [closeButton cell];

[closeButton setBezelStyle:NSCircularBezelStyle];
[closeButton setTitle:@""];
[closeButton setBordered:NO];    
[closeButton setImage:[NSImage imageNamed:NSImageNameStopProgressFreestandingTemplate]];
[closeButtonCell setImageScaling:NSImageScaleProportionallyDown];
[closeButtonCell setBackgroundColor:[NSColor clearColor]];
[closeButton setAlphaValue:0.5];

//Calling the button:
[self.window addViewToTitleBar:closeButton atXPosition:8];

これで、xcode のウェルカム スクリーンにかなり近づいたように見えるはずです。必要に応じて、ホバー効果をプログラムすることもできます。これは非常に簡単です。

于 2014-02-28T15:35:28.230 に答える
1

次の 2 つのオプションがあります。

  1. レイヤーの影のプロパティを使用します。
  2. drawRect ルーチンで影を自分で描画します。これを機能させるには、丸みを帯びた角を設定せずに、挿入パスを使用して角の丸い長方形とその影を描画します。

コード:

@interface RoundedOuterShadowView : NSView {
}

@end

@implementation RoundedOuterShadowView

- (id)initWithFrame: (NSRect)frameRect
{
    self = [super initWithFrame: frameRect];
    if (self != nil) {
    }

    return self;
}

// Shared objects.
static NSShadow *borderShadow = nil;

- (void)drawRect: (NSRect)rect
{
    [NSGraphicsContext saveGraphicsState];

    // Initialize shared objects.
    if (borderShadow == nil) {
        borderShadow = [[NSShadow alloc] initWithColor: [NSColor colorWithDeviceWhite: 0 alpha: 0.5]
                                                offset: NSMakeSize(1, -1)
                                            blurRadius: 5.0];
    }

    // Outer bounds with shadow.
    NSRect bounds = [self bounds];
    bounds.size.width -= 20;
    bounds.size.height -= 20;
    bounds.origin.x += 10;
    bounds.origin.y += 10;

    NSBezierPath *borderPath = [NSBezierPath bezierPathWithRoundedRect: bounds xRadius: 5 yRadius: 5];
    [borderShadow set];
    [[NSColor whiteColor] set];
    [borderPath fill];

    [NSGraphicsContext restoreGraphicsState];
}

@end
于 2013-11-13T09:04:01.490 に答える
0

これを試して:

- (id)initWithContentRect:(NSRect)contentRect
                styleMask:(NSUInteger)windowStyle   
                  backing:(NSBackingStoreType)bufferingType
                    defer:(BOOL)deferCreation
{
    self = [super
            initWithContentRect:contentRect
            styleMask:NSBorderlessWindowMask | NSResizableWindowMask
            backing:bufferingType
            defer:deferCreation];
    if (self)
    {
        [self setOpaque:NO];
       [self setBackgroundColor:[NSColor clearColor]];            

    }

      [self setHasShadow:YES];


    [self setMovableByWindowBackground:YES];
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(didBecomeKey:) name:NSWindowDidBecomeKeyNotification object:self];

    return self;
}

-(void)didBecomeKey:(NSNotification *)notify{
    [self performSelector:@selector(invalidateShadow) withObject:nil afterDelay:.1];
}
于 2014-01-20T23:28:27.023 に答える
0

以前のプロジェクトでこれに出くわしました: レイヤーに裏打ちされたビューは影を生成しません。ウィンドウのコンテンツ ビューを「通常の」(レイヤーを使用しない) ビューに設定すると、影が表示されます。

于 2013-11-12T21:33:50.373 に答える