パン ジェスチャ認識エンジンを追加する

サンプルのダウンロードサンプルのダウンロード

パン ジェスチャは、画面周辺の指の動きを検出し、その動きをコンテンツに適用するために使用され、PanGestureRecognizer クラスを使用して実装されます。 パン ジェスチャの一般的なシナリオは、イメージを水平方向や垂直方向にパンし、イメージをそのイメージのディメンションより小さいビューポートで表示するときに、そのコンテンツがすべて表示されるようにすることです。 これは、イメージをビューポート内で移動することによって実現され、この記事でその方法について説明します。

ユーザー インターフェース要素をパン ジェスチャを使用して移動できるようにするには、PanGestureRecognizer インスタンスを作成し、PanUpdated イベントを処理し、新しいジェスチャ認識エンジンをユーザー インターフェイス要素の GestureRecognizers コレクションに追加します。 次に示すのは、Image 要素に関連付けられている PanGestureRecognizer のコード例です。

var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += (s, e) => {
  // Handle the pan
};
image.GestureRecognizers.Add(panGesture);

次のコード例に示すように、XAML でもこれを実現できます。

<Image Source="MonoMonkey.jpg">
  <Image.GestureRecognizers>
    <PanGestureRecognizer PanUpdated="OnPanUpdated" />
  </Image.GestureRecognizers>
</Image>

OnPanUpdated イベント ハンドラー用のコードが分離コード ファイルに追加されます。

void OnPanUpdated (object sender, PanUpdatedEventArgs e)
{
  // Handle the pan
}

パン コンテナーの作成

このセクションにはフリーフォームのパンを実行する汎用のへルパー メソッドが含まれており、一般的に画像内やマップ内の移動に適しています。 この操作を実行するためのパン ジェスチャの処理では、ユーザー インターフェイスを変換するための多少の計算が必要です。 この計算はラップされたユーザー インターフェイス要素の境界内のパンにのみ使用されます。 次に示すのは、PanContainer クラスのコード例です。

public class PanContainer : ContentView
{
  double x, y;

  public PanContainer ()
  {
    // Set PanGestureRecognizer.TouchPoints to control the
    // number of touch points needed to pan
    var panGesture = new PanGestureRecognizer ();
    panGesture.PanUpdated += OnPanUpdated;
    GestureRecognizers.Add (panGesture);
  }

  void OnPanUpdated (object sender, PanUpdatedEventArgs e)
  {
    ...
  }
}

このクラスでユーザー インターフェイス要素をラップして、ラップされたユーザー インターフェイス要素がそのジェスチャでパンされるようにすることができます。 次に示すのは、Image 要素をラップしている PanContainer の XAML のコード例です。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:PanGesture"
             x:Class="PanGesture.HomePage">
    <ContentPage.Content>
        <AbsoluteLayout>
            <local:PanContainer>
                <Image Source="MonoMonkey.jpg" WidthRequest="1024" HeightRequest="768" />
            </local:PanContainer>
        </AbsoluteLayout>
    </ContentPage.Content>
</ContentPage>

次に示すのは、PanContainer で C# ページ内の Image 要素をラップする方法のコード例です。

public class HomePageCS : ContentPage
{
  public HomePageCS ()
  {
    Content = new AbsoluteLayout {
      Padding = new Thickness (20),
      Children = {
        new PanContainer {
          Content = new Image {
            Source = ImageSource.FromFile ("MonoMonkey.jpg"),
            WidthRequest = 1024,
            HeightRequest = 768
          }
        }
      }
    };
  }
}

両方の例で、WidthRequestHeightRequest の各プロパティは表示されるイメージの高さと幅の値に設定されます。

Image 要素がパン ジェスチャを受け取ると、表示されているイメージがパンされます。 次のコード例に示すように、PanContainer.OnPanUpdated メソッドによってパンが実行されます。

void OnPanUpdated (object sender, PanUpdatedEventArgs e)
{
  switch (e.StatusType) {
  case GestureStatus.Running:
    // Translate and ensure we don't pan beyond the wrapped user interface element bounds.
    Content.TranslationX =
      Math.Max (Math.Min (0, x + e.TotalX), -Math.Abs (Content.Width - App.ScreenWidth));
    Content.TranslationY =
      Math.Max (Math.Min (0, y + e.TotalY), -Math.Abs (Content.Height - App.ScreenHeight));
    break;

  case GestureStatus.Completed:
    // Store the translation applied during the pan
    x = Content.TranslationX;
    y = Content.TranslationY;
    break;
  }
}

このメソッドにより、ユーザーのパン ジェスチャに基づいて、ラップされたユーザー インターフェイス要素の表示可能コンテンツが更新されます。 これは、 インスタンスの TotalXPanUpdatedEventArgsTotalY の各プロパティを使用して、パンの方向と距離を計算します。 App.ScreenWidthApp.ScreenHeight の各プロパティはそのビューポートの高さと幅を提供し、プラットフォーム固有の各プロジェクトによってそのデバイスの画面の幅と高さの値に設定されます。 TranslationXTranslationY の各プロパティが計算済みの値に設定されることで、ラップされたユーザー要素がパンされます。

画面全体を占拠しない要素内でコンテンツをパンすると、そのビューポートの高さと幅はその要素の HeightWidth の各プロパティから取得できます。

注意

高解像度のイメージを表示すると、アプリのメモリの占有領域が大幅に増える場合があります。 そのため、必要な場合にのみ作成し、アプリで不要になったらすぐに解放する必要があります。 詳細については、「イメージ リソースを最適化する」を参照してください。