🐰

AppKitで左右カーソルキーでフォーカスリングを移動する

2024/02/23に公開

macOS AppKitのコントロールはキーボードナビゲーションに対応しており、フォーカスが当たると周囲にフォーカスリングが描画される仕組みになっています。キーボードナビゲーションはTabで次のキービューに移動、Shift Tabで前のキービューに移動させることができます。この操作を別のキーの組み合わせ、例えば左右カーソルキーでも操作できるようにしてみようと思います。


フォーカスリング

フォーカスリングを表示してキーボードナビゲーションを使えるようにするには、システム設定でキーボードナビゲーションを有効にする必要があります。


対応させたいビュークラスにてkeyDown()をオーバーライドし、ウインドウに対して次のメソッドを呼び出します。

左右カーソルキーはNSEvent.specialKeyで判定します。

class MyView: NSView {

	override func keyDown(with event: NSEvent) {
		if event.isLeftArrow {
			// ←(左カーソルキー)で前のキービューにフォーカスを移す; shift tab と同等効果
			window?.selectPreviousKeyView(event) // senderはnilでもいいかも
			return
		}
		if event.isRightArrow {
			// →(右カーソルキー)で次のキービューにフォーカスを移す; tab と同等効果
			window?.selectNextKeyView(event)
			return
		}
		
		super.keyDown(with: event)
	}
	
}

extension NSEvent {

	/// ←判定
	var isLeftArrow: Bool {
		specialKey == .leftArrow
	}
	
	/// →判定
	var isRightArrow: Bool {
		specialKey == .rightArrow
	}

}

キービュー(key view)とは、キーボード等のイベントを受け取ることができるビューです。キービューがfirst responderになるとそのビューに対してキーボードイベントを送ることができるようになります。キーボードナビゲーション(フォーカスリングの移動)はキービュー間で行われます。

キービューでもisHidden == trueで隠れている場合はフォーカスが当たらず、イベントも届きません。

キービュー状態やキーボードイベントの制御を行うには、canBecomeKeyViewacceptsFirstResponderプロパティをオーバーライドして対応します。

関連:
https://zenn.dev/usagimaru/articles/fb10c16654d030

Discussion