7
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Preferencesみたいなツールバータブウィンドウを作る

Last updated at Posted at 2016-07-14

よくあるアプリのPreferencesウィンドウみたいなのを作ります。
ツールバーがタブの役割をしていて、タブを選択すると画面が切り替わります
スクリーンショット 2016-07-14 17.42.03.png

作り方

既存のツールバーをいじってもなかなかうまくいかなかったのですが、NSTabViewControllerなるものを使えば簡単にできます。

TabViewControllerをStoryboardに追加

スクリーンショット 2016-07-14 17.50.06.png

TabViewControllerをStoryboardに追加します。
そして、WindowControllerと関連づいているViewControllerを削除し、WindowControllerのwindow contentに追加したTabViewControllerを割り当てます。

TabViewControllerの設定ですが、StyleをToolbarに変更します。
スクリーンショット 2016-07-14 18.01.09.png

TabViewControllerのChildViewControllerをいじる

適当にいじります。今回は適当なラベルを追加しました。
今んとこViewControllerの構成は以下のようになっています。

スクリーンショット_2016-07-14_17_56_23.png

ToolbarItemをいじる

上記まででタブでの画面切り替え自体は出来ますが、タブのアイコンがない状態ですのでシステムのアイコンをつけてみます。
(システムのアイコンについての詳細は、System-Provided Imagesを参照してみてください。)

  1. NSTabViewControllerのサブクラスを作成。
  2. InterfaceBulder上でNSTabViewControlleを手順1で作ったクラスに変更
  3. InterfaceBulder上でTabViewControllerの下にNSTabViewItemがありますのでこれを手順1のサブクラスのOutletに追加。
スクリーンショット 2016-07-14 18.09.13.png 4. NSTabViewControllerのサブクラスのコード内で、手順3で作ったオブジェクトのアイコンを設定。
TabViewController.swift
class TabViewController: NSTabViewController {

    @IBOutlet weak var generalItem: NSTabViewItem!
    @IBOutlet weak var accountItem: NSTabViewItem!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // アイコン設定
        accountItem.image = NSImage(named: NSImageNameUserAccounts)
        generalItem.image = NSImage(named: NSImageNamePreferencesGeneral)
    }
}

iOSのTabBarControllerみたいな感じでできました。

(追記)タブ選択時に、Windowサイズを変更する

それぞれのタブのViewのサイズが異なる場合、タブ選択時にサイズを変更してあげる必要があります。

一番簡単なのは、AutoLayoutで各Viewのサイズを固定してしまうことです。
しかしこのやり方では、アニメーションがつかなかったので、以下のように実装しました。

やり方

  1. (必要なら)windowのリサイズを無効にする
スクリーンショット_2016-07-14_19_46_06.png
  1. TabViewをTabViewControllerのDelegateに設定する。
  2. TabViewControllerにデリゲートメソッド tabView(tabView: NSTabView, willSelectTabViewItem tabViewItem: NSTabViewItem?) を追加し実装する。

上記のデリゲートメソッドはタブを選択した時に呼ばれます。この時にWindowサイズを変更するコードを実装します。

ソースコード

TabViewController.swift
class TabViewController: NSTabViewController {

    @IBOutlet weak var generalItem: NSTabViewItem!
    @IBOutlet weak var accountItem: NSTabViewItem!
    
    enum TabViewIdentifier: String {
        case GeneralIdentifier = "General"
        case AccountIdentifier = "Account"
        
        var tabViewType: TabViewType {
            switch self {
            case GeneralIdentifier:
                return TabViewType.General
            case AccountIdentifier:
                return TabViewType.Account
            }
        }
    }
    
    enum TabViewType: Int {
        case General
        case Account
        
        var windowSize: CGSize {
            switch self {
            case .General:
                return CGSizeMake(450, 160) //適当
            case .Account:
                return CGSizeMake(450, 280) //適当
            }
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        accountItem.image = NSImage(named: NSImageNameUserAccounts)
        generalItem.image = NSImage(named: NSImageNamePreferencesGeneral)
    }
    
    // タブを選択した時に呼ばれる
    override func tabView(tabView: NSTabView, willSelectTabViewItem tabViewItem: NSTabViewItem?) {
        guard let window = self.view.window else { return }
        guard let identifier = tabViewItem?.identifier as? String else { return }
        guard let tabViewIdentifier = TabViewIdentifier(rawValue: identifier) else { return }
        
        let type = tabViewIdentifier.tabViewType
        let contentSize = type.windowSize
        let newWindowSize = window.frameRectForContentRect(CGRectMake(0, 0, contentSize.width, contentSize.height)).size
        
        var frame = window.frame
        frame.origin.y += frame.size.height
        frame.origin.y -= newWindowSize.height
        frame.size = newWindowSize
        
        // サイズ変更
        self.view.window?.setFrame(frame, display: false, animate: true)
    }
}
7
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?