左右のフリック操作を検出する

Mono for Androidで左右のフリック操作を検出したかったのでKazzzさんが書かれたサンプルコードを移植してみた。

using Android.Views;

public class FlickListener : Java.Lang.Object, View.IOnTouchListener
{
  public enum Direction
  {
    Left,
    Right
  }
  private readonly GestureDetector detector;
  public delegate void OnFlickHandler (Direction direction);
  public event OnFlickHandler OnFlick;

  public FlickListener (Android.Content.Context context)
  {
    detector = new GestureDetector (context, new FlickGestureDetector (this));
  }

  public bool OnTouch (View v, MotionEvent e)
  {
    return detector.OnTouchEvent (e);
  }

  private class FlickGestureDetector : Java.Lang.Object, GestureDetector.IOnGestureListener
  {
    private readonly FlickListener owner;
    public FlickGestureDetector (FlickListener owner)
    {
      this.owner = owner;
    }

    public bool OnDown (MotionEvent e)
    {
      return true;
    }

    public bool OnFling (MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
    {
      if (owner.OnFlick != null)
        owner.OnFlick (e1.GetX () < e2.GetX () ? Direction.Right : Direction.Left);
      return true;
    }

    public void OnLongPress (MotionEvent e) {}

    public bool OnScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
    {
      return true;
    }

    public void OnShowPress (MotionEvent e) {}

    public bool OnSingleTapUp (MotionEvent e)
    {
      return true;
    }
  }
}

例えばVireFlipperなら以下の様な使い方が可能。

ViewFlipper vf = main.FindViewById<ViewFlipper> (Resource.Id.viewFlipper);
FlickListener fgl = new FlickListener (this);
vf.SetOnTouchListener (fgl);
fgl.OnFlick += delegate(FlickListener.Direction direction) {
  if (direction == FlickListener.Direction.Left)
    vf.ShowPrevious ();
  else
    vf.ShowPrevious ();
};

FrameLayoutでも検出できた。


以下が参考にしたKazzzさんのサイト。

  • Kazzzの「JとNの狭間で」 - TouchEventをGestureDetectorで置き換える

http://d.hatena.ne.jp/Kazzz/20100615/p1