8

ここに別のNSWindow質問があります...この方法で作成された透明なボーダーレスウィンドウがあります...

- (id)initWithView:(NSView *)view anchorPoint:(NSPoint)anchorPoint position:(NSPoint)position distance:(CGFloat)distance {
  if ( !view ) {
    return nil;
  }

  NSSize size = view.intrinsicContentSize;
  NSRect contentRect = NSMakeRect( 0, 0, size.width, size.height );

  self = [super initWithContentRect:contentRect
                          styleMask:NSBorderlessWindowMask
                            backing:NSBackingStoreBuffered
                              defer:NO];

  if ( !self ) {
    return nil;
  }

  _windowView = view;
  _anchorPoint = anchorPoint;
  _position = position;
  _distance = distance;

  [self setContentView:_windowView];

  [self setExcludedFromWindowsMenu:YES];
  [self setMovableByWindowBackground:NO];

  [self setOpaque:NO];
  [self setBackgroundColor:[NSColor clearColor]];

  [self setHasShadow:YES];
  [self useOptimizedDrawing:YES];

  [self setReleasedWhenClosed:NO];

  [self setFrame:[self windowRectWithSize:contentRect.size] display:YES];

  [self setAnchorAttribute:NSLayoutAttributeTop forOrientation:NSLayoutConstraintOrientationVertical];
  [self setAnchorAttribute:NSLayoutAttributeCenterX forOrientation:NSLayoutConstraintOrientationHorizontal];

  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(viewFrameDidChange:)
                                               name:NSViewFrameDidChangeNotification
                                             object:nil];

  return self;
}

... とviewFrameDidChange:定義されています ...

- (void)viewFrameDidChange:(NSNotification *)note {
  if ( note.object != self.contentView ) {
    return;
  }

  [self display];
  [self setHasShadow:NO];
  [self setHasShadow:YES];
}

...これが適切なNSWindow影を持つ唯一の方法です。言い換えると、ウィンドウのサイズが変わるたびに を呼び出す必要がdisplayありsetHasShadow:NOます。setHasShadow:YESそうしないと、ウィンドウの影が不自由になります (ウィンドウ全体ではなく、ウィンドウの一部など)。

これは、高さのアニメーション化を開始するまで機能します。高さをアニメーション化すると、影は正しく再計算されて表示されるのですが、ウィンドウ全体と影がちらつき、かなり醜いです。

影がちらつく理由がわかりましたか?を に置き換えてみたのですがdisplay、まったくうまくいかず、影の表示がおかしくなりました。setHasShadow:NO/YES[self invalidateShadow]

ちらつきを避けるために、ボーダーレス/透明ウィンドウで影付きのウィンドウの高さをどのようにアニメーション化する必要がありますか?

揺らめく影の動画はこちら。http://d.pr/v/lbkQ

4

2 に答える 2

2

アニメーションの開始時に影をオフにして、終了したら再びオンにする方がよいかもしれません。アニメーション中にこの設定を切り替えないでください。これは他のウィンドウでも見たことがあると思いました。

于 2013-04-22T17:32:49.707 に答える
2

影の計算と描画は、非常にリソースを消費する操作です。したがって、フレームが変わるたびにシャドウを無効にして再計算することはお勧めしません。その上、NSWindowDelegateには–windowDidResize:メソッドがあるのに、なぜオブザーバーを使用するのでしょうか。

  1. ウィンドウのサイズを変更するにはどうすればよいですか? おそらくNSResizableWindowMask、ウィンドウのスタイル マスクに追加するとうまくいくでしょうか? 試してみてください。

  2. 別の提案 - ウィンドウのコンテンツがウィンドウに合わせて正しくサイズ変更されることを確認してください。ウィンドウを透明に設定します。ただし、ウィンドウ内にコンテンツがない場合、影は表示されません。ビューを置き換えるのではなく、既存のウィンドウの contentView にサブビューとして追加することもできます。

私のプロジェクトにはほぼ同じ設定があり、ウィンドウのサイズを変更すると、ウィンドウの影が正しく表示されることがわかります。

PS 推奨事項: オブジェクトの初期化メソッドで「self」に依存しないでください。まだ完全に使用できる状態ではない可能性があります。最小値で初期化し、コントローラーで作成した後にウィンドウを調整します (たとえば、setFrame:display が正しいサイズで期待どおりに動作するかどうかを確認できません)。あなたが持っているグリッチもこれに関連している可能性があります。

于 2013-05-01T20:14:17.883 に答える