feed

2020年03月19日, 編集履歴

ノブなしNSSliderでシークバーを作る

久しぶりにアプリをリリースしました。「Silver Baton」という、Music.appで再生中の曲の情報表示や再生・一時停止等の操作ができるmacOSアプリです。

上記画像のようなコントロールパネルをトラックパッドの3/4本指タップやマウスの右ダブルクリック、ミドルクリックで呼び出せるところがミソです。

さて、Silver Batonでは曲の進行具合の表示と変更のためにシークバーを実装しています(上記画像のウィンドウ最下部の青いバー部分)。

NSProgressIndicatorは何らかの進捗具合を表示するにはうってつけですが、「Indicator」の示すとおり、「表示」に特化していてマウス操作は受け付けません。

そこで、マウス操作を受け付けるNSSliderを利用しました。素のNSSliderには大きなノブが付いています(上記画像のシークバー上部の音量調節NSSliderの白丸)。ノブは邪魔なので、表示させなくするためにNSSliderCellをサブクラス化しました。

import AppKit

class KnoblessSliderCell: NSSliderCell {
  override func knobRect(flipped: Bool) -> NSRect {
    return NSRect.zero
  }
}

let slider1 = NSSlider(target: nil, action: nil)
slider1.doubleValue = 0.5

let slider2 = NSSlider(target: nil, action: nil)
slider2.cell = KnoblessSliderCell()
slider2.doubleValue = 0.5

slider1が通常のスライダ、slider2がノブなしスライダです。NSSliderCellfunc knobRect(flipped: Bool) -> NSRectをオーヴァライドしてサイズゼロのNSRectを返すことで、ノブを描画しないようにしました。ノブが描画されなくても、通常通りマウスのクリックやドラッグに反応してくれます。

欲を言えば、マウスオーヴァ時だけノブを出したりバーを太くしたりしたほうが良さげですが、今回はここまで。