Developer's Blog

Lion の新しいスワイプジェスチャー API を試す

こんにちは、Sleipnir for Mac でジェスチャー機能を担当しました宮本です。

Lion では標準のページ切り替えジェスチャーが変更されました。
Snow Leopard までは左右のスワイプでパッとページが切り替わっていましたが、Lion からは iOS と同じように指の動きについてくるなめらかなページ切り替えができます。

タッチイベントを自前で処理して実装するとかなり大変ですが、10.7以降には便利な API があって実は簡単に実現できます。 今回は、この API の使い方を紹介したいと思います。 ちなみに、Sleipnir for Mac でもタブ切り替えジェスチャーにこの API を使っています。

新しいジェスチャーのポイントは次のメソッドです。

- (void)trackSwipeEventWithOptions:(NSEventSwipeTrackingOptions)options
          dampenAmountThresholdMin:(CGFloat)minDampenThreshold
                               max:(CGFloat)maxDampenThreshold
                      usingHandler:(void (^)(CGFloat gestureAmount, 
                                             NSEventPhase phase, 
                                             BOOL isComplete, 
                                             BOOL *stop))handler;

指に合わせて View を動かしたり、指を離したらアニメーションしたり、ページが切り替えられない方向ではあまり View が動かないようにしたりなど、すべてこのメソッドで片付けることができます。 Safari の戻る進むジェスチャーやプレビューのページ送りと同じようなものもこれだけで簡単に実装できます。

このメソッドは NSEvent のインスタンスメソッドで、スクロールイベント(scrollWheel:)を受けてるところで呼びだします。 すると、スクロールイベントがこなくなって、代わりに handler のブロックが実行されるようになります。 始め、gestureAmount は0で、スクロールを続けると、だんだん増えるか減っていきます。 ちょうど1か-1になった時が前か次のページに切り替わるべきタイミングになっているので、この値に合わせて View を動かすとうまくいきます。 スクロールをやめると、その時の gestureAmount から -1(前のページに切り替え), 0(始めの状態に戻る), 1(次のページに切り替え) のいずれかの値まで連続的に変化するので、ただ gestureAmount に合わせて frame を変更するだけでアニメーションが実現できてしまいます。

実際に書いてみるとこんな感じになります。

- (void)scrollWheel:(NSEvent *)event 
{
     // ジェスチャーのスクロールかどうか
    if ([event phase] == NSEventPhaseNone) return;
    // 横スクロールかどうか
    if (fabsf([event scrollingDeltaX])

handler 以外の引数の説明もしておきます。
(NSEventSwipeTrackingOptions)options
NSEventSwipeTrackingLockDirection:デフォルト
NSEventSwipeTrackingClampGestureAmount:gestureAmountが-1以下になったり、1以上にならなくなります。
(CGFloat)minDampenThreshold
左側にあるページの数をいれるといいようです。大きい値を入れると、gestureAmount の変化量が大きくなってより左右に切り替えやすくなります。0をいれるとその方向には切り替えられなくなります。また、マイナスの値でないといけません。
(CGFloat)maxDampenThreshold
右側にあるページの数をいれます。

上のコードに
if (![NSEvent isSwipeTrackingFromScrollEventsEnabled]) return;
とあるように、Lion でもシステム環境設定でスクロールによるスワイプジェスチャーをやめて、Snow Leopard と同じ挙動にすることができます。 なので、そういう時の為にスワイプイベントも受けられるようにするべきです。

// 従来のスワイプジェスチャー
- (void)swipeWithEvent:(NSEvent *)event
{
     if ([event deltaX] > 0) {
         // 進む処理
     } else {
         // 戻る処理
     }
}

Lion では iOS ライクな動きを作りやすいように API がパワーアップしています。 他にも、NSTableView が View ベースで作れるようになっていてアニメーションやイベント処理がしやすくなっていたりと、うれしい変更が盛りだくさんです。 ぜひ、色々調べてみてください。下のリリースノートがまとまっていてお勧めです。今回のジェスチャーについても書いてあります。
Mac OS X Developer Release Note

Copyright © 2019 Fenrir Inc. All rights reserved.