この記事は Goodpatch Advent Calendar 2015 8日目の記事です。昨日は
@subuta_nico のWallaby.jsを活用したテスト駆動開発についてでした!
こんにちは@hanamijuです。GoodpatchでOSXアプリを開発しています。
OSX Yosemiteからツールバーやサイドメニューなどに、擦りガラスのようなブラー効果をかけれるようになりました。こちらのやり方についてご紹介します。
とりあえずブラーをかける
ブラーのかかったViewを表示するためにYosemite以降では特別がんばる必要はありません。
実際に表示するためにはNSViewをいじるのではなく、NSVisualEffectViewというNSViewのサブクラスを使用します。
やり方
Interface BuilderのViewのクラス名をいじるだけです。
結果
超簡単ですね。
ちなみに、Inteface BuilderにもNSVisualEffectViewがあります。
ここからViewに設定してもブラーのかかったViewを表示することができます。
ブラーをかける対象について(In behind-window or With in-window)
NSVisualEffectViewがブラーをかける対象は以下の二つがあります。
- In behind-window (ブラーがかかっているViewの背景にブラーをかける)
- With in-window (ブラーがかかっている同一ウィンドウ内でブラーをかける)
In behind-window
こちらのわかりやすい例はFinderのサイドメニューです。ウィンドウの外側(の壁紙)に対してブラーがかかっています。背景が透けているのでウィンドウレベルでの階層の視覚化ができます。
With in-window
こちらのわかりやすい例としてはMapsの経路表示です。ウィンドウ内の階層を意識させたい時に使えます。
↓では経路表示のViewのブラーはその下のMapに対してかかっていることがわかります。
やり方
NSVisualEffectViewのblendingMode
を変更するだけです。
blendingMode
をWithinWindow
にする場合はview.wantsLayer = true
にする必要があります。
effectView.wantsLayer = true // これないと実行時に落ちる。
effectView.blendingMode = .WithinWindow
ブラーの上でベタ塗りのViewを重ねたい
NSVisualEffectViewにControlを乗せるといい感じに色がブレンディングされます。
いちいちControlの設定変更を行わないで済むので楽なのですが、ブラーの上にブラーのかかっていないViewを重ねたい場面もあると思います。簡単にできそうなのですがちょっとつまづいたのでやり方を残します。
サンプル
以下のように、ブラーの上にベタ塗りのViewを貼り付けるサンプルを作ります。
StoryBoardをいじる
View → VisualEffectView → ベタ塗りしたいView(今回はHogeView1) → その上のコントロール っていう階層でコンポーネントを配置します。
余談ですが、VisualEffectViewのAppearanceはデフォルトでDarkに設定されているのでInterfaceBuilder上で設定を変えるにはView - Appearanceの設定をVibrant Lightに設定します。
(VisualEffectViewの項目になかったので一瞬えっ!ってなりました...)
この状態でビルドしてみた
このように、HogeViewがブラーに同化されてしまいました。
以下で、背景色を設定していきます。
コーディング
普通に実装するとdrawRect()
でNSColor.whiteColor().set()
的なことをする2のですが、これだと上図と同じくHogeViewにブラーがかかったままになります。
それじゃどうするのかというとCALayerレベルで設定します。
まずHogeViewをOutletに設定してwantsLayer = true
します。
その後HogeViewのlayer.backgroundColor
で背景色の設定をします。
import Cocoa
class ViewController: NSViewController {
@IBOutlet weak var hogeView: HogeView!
override func viewDidLoad() {
super.viewDidLoad()
hogeView.wantsLayer = true
}
}
class HogeView: NSView {
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
//NSColor.whiteColor().set() <- コレ呼んでも背景ベタ塗りされないよ
}
override func layout() {
super.layout()
self.layer?.backgroundColor = NSColor.whiteColor().CGColor // 背景色
// お好みでどうぞ
self.layer?.borderColor = NSColor.grayColor().CGColor // ボーダー色
self.layer?.borderWidth = 2 // ボーダーの太さ
self.layer?.cornerRadius = 8 // 角丸の半径
}
}
結果
できて............ない!
Labelの背景にブラーがかかっています。
これを直すにはLabelの背景色を透明にする必要があります。
InterfaceBuilder上でDisplay - Draws Backgroundにチェックを入れた状態でBackgroundのAlphaを0に設定します。
ちょっとイマイチな感じですが、これで最初の画像のように上手く表示することができます。
TableViewにブラーをかけたい
TableView(OutlineView)にブラーをかける時はNSVisualEffectViewを使用するのではなく、TableView自体にブラー設定するプロパティが存在するのでそれを使います。
やり方
InterfaceBuilderから対象のTableViewを選択して、TableView - Highlightの項目をSource Listにするだけです。
Cellの選択状態の背景色をブラーに設定したい
私が調べた限りではFinderのサイドバーのように、TableViewにあるCellが選択状態の時の背景をブラーに設定する方法は見つかりませんでした。(知っている方いたら教えて欲しいです。)
ですが、それっぽく見せる方法は存在します。
やり方
TableViewのサブクラスを作り、FirstResponderを受け付けなくすると選択した時に濃いブラーがかかった状態になります3。
以下のコードをTableViewのサブクラスに記述します。
override var acceptsFirstResponder: Bool { return false }
参考:How to get the source lists selection highlight to use the Dark Vibrancy appearance in OS X 10.10?
おわりに
以上、NSViewのブラーまわりの話でした。
公式ドキュメント以外あんまり情報が転がってないのでちょっと調べるのが手間でしたが分かれば簡単です。
明日はGoodpatchのProject Managerの@Hasedaから、エディタ初心者がSublimeTextでHTML5/CSS3を書く環境を作るのに苦労した話をお届けします。お楽しみに!