NSToolbar でサイズが切り替わる設定画面のような WIndow を作る
下のようなXcode の設定ウィンドウのように NSToolbar が上部にあり、表示内容のサイズをアニメーション付きで変わるものを作ります。
storyboard
- NSWindowController を用意します。
- NSToolbar をセットし、下のように必要な NSToolbarItem を追加したりします。
NSWIndowController に紐付いている ViewController の view (NSView) を flipped = true を返すものにします。(理由は後述します。)
それぞれの設定画面の ViewController として作ります。必要な場合、レイアウトをします。
- NSToolbarItem の action 先を紐付けます。
code
- 上で紐付けると NSToolbarItem として event が来るので設定した identifier から必要な ViewController を生成します。
- 生成した ViewController のサイズを計算し( autolayout している場合は fittingSize )、現在の View の高さとの差分をとります。(これも理由は後述します)
- ContentViewController の childViewController から既存のものを削除し、生成した ViewController を追加し、view も追加します。
- 生成した view の frame を指定します。(幅は既存の view, window と同じ、高さは上で計算したサイズの高さ, origin は 0, 0 で大丈夫です。これは上で flipped になっているからです。flipped でない場合は座標系が左下基準なので Window の下部に張り付いてアニメーションします)
NSWindow.setFrame(_:display:animate:)
で animation 付きでサイズを指定します。これも上と同じ理由で、origin は現在の場所から上で計算した差分分を引きます。そうしないとサイズのみを変更した場合 Window の下部が固定されて上部が移動しますので不自然です*1
長くて文章にするとわかりづらいですがコードだとこういう感じです。
let fittingSize = newVC.view.fittingSize let addition = fittingSize.height - self.contentViewController.view.frame.size.height if let oldVC = self.contentViewController?.childViewControllers.first { oldVC.removeFromParentViewController() oldVC.view.removeFromSuperview() } self.contentViewController?.addChildViewController(newVC) self.contentViewController?.view.addSubview(newVC.view) let windowFrame = self.window!.frame newVC.view.frame = NSMakeRect(0, 0, windowFrame.size.width, fittingSize.height) self.window!.setFrame(NSMakeRect(windowFrame.origin.x, windowFrame.origin.y - addition, windowFrame.size.width, windowFrame.size.height + addition ), display: true, animate: true)