かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

タッチイベントを処理しよう その2

前回は、非常にプリミティブなタッチイベントの処理の仕方を見てみました。今回は、もうちょっと素敵な感じで処理できる方法を見てみようと思います。

使うイベントは以下の3つです。

  • ManipulationStarted
    • タッチが開始されたときに起きるイベントです。
  • ManipulationDelta
    • タッチ中に指が動いたときに起きるイベントです。
  • ManipulationCompleted
    • タッチが終わった時のイベントです。

各イベントのイベント引数から各種情報を取得することが出来ます。簡単に画面に出してみるために以下のようなプログラムを書いてみました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Diagnostics;

namespace WindowsPhoneApplication8
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();
        }

        private void PhoneApplicationPage_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {
            // ManipulationOriginでタッチの開始場所を取得できる
            Debug.WriteLine("** Started");
            Debug.WriteLine("  ManipulationOrigin: " + e.ManipulationOrigin);
        }

        private void PhoneApplicationPage_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            // 色々情報が取れるけど、0,0が多くて何に使えるのか・・・
            Debug.WriteLine("** Delta");
            Debug.WriteLine("  ManipulationOrigin: " + e.ManipulationOrigin);
            Debug.WriteLine("  DeltaManipulation.Scale: " + e.DeltaManipulation.Scale);
            Debug.WriteLine("  DeltaManipulation.Translation: " + e.DeltaManipulation.Translation);
            Debug.WriteLine("  CumulativeManipulation.Scale: " + e.CumulativeManipulation.Scale);
            Debug.WriteLine("  CumulativeManipulation.Translation: " + e.CumulativeManipulation.Translation);
        }


        private void PhoneApplicationPage_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
        {
            // ManipulationOriginでタッチの終了場所を取得できる。
            // TotalManipulationでタッチ開始から終了までに、どれくらい動いたかとれる
            Debug.WriteLine("** Completed");
            Debug.WriteLine("  ManipulationOrigin: " + e.ManipulationOrigin);
            Debug.WriteLine("  TotalManipulation.Scale: " + e.TotalManipulation.Scale);
            Debug.WriteLine("  TotalManipulation.Translation: " + e.TotalManipulation.Translation);
        }

    }
}

XAMLは、以下のような感じです。基本的にイベントを登録してるだけで、プロジェクトを新規作成したときのままです。

<phone:PhoneApplicationPage 
    x:Class="WindowsPhoneApplication8.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True" 
    <!-- イベント登録!! -->
    ManipulationStarted="PhoneApplicationPage_ManipulationStarted"
    ManipulationDelta="PhoneApplicationPage_ManipulationDelta"
    ManipulationCompleted="PhoneApplicationPage_ManipulationCompleted">
    <!-- 省略 -->
</phone:PhoneApplicationPage>

実行してエミュレータ上で真ん中らへんをクリックして、そのまま左にマウスをドラッグしてマウスを離してみました。デバッグウィンドウに出力された情報は、以下のような感じです。

** Started
  ManipulationOrigin: 237,382
** Delta
  ManipulationOrigin: 200,382
  DeltaManipulation.Scale: 0,0
  DeltaManipulation.Translation: -11,0
  CumulativeManipulation.Scale: 0,0
  CumulativeManipulation.Translation: -11,0
** Delta
  ManipulationOrigin: 195,384
  DeltaManipulation.Scale: 0,0
  DeltaManipulation.Translation: -5,2
  CumulativeManipulation.Scale: 0,0
  CumulativeManipulation.Translation: -16,2
** Delta
  ManipulationOrigin: 189,384
  DeltaManipulation.Scale: 0,0
  DeltaManipulation.Translation: -6,0
  CumulativeManipulation.Scale: 0,0
  CumulativeManipulation.Translation: -22,2
** Delta
  ManipulationOrigin: 173,386
  DeltaManipulation.Scale: 0,0
  DeltaManipulation.Translation: -16,2
  CumulativeManipulation.Scale: 0,0
  CumulativeManipulation.Translation: -38,4
** Delta
  ManipulationOrigin: 166,386
  DeltaManipulation.Scale: 0,0
  DeltaManipulation.Translation: -7,0
  CumulativeManipulation.Scale: 0,0
  CumulativeManipulation.Translation: -45,4
** Delta
  ManipulationOrigin: 159,386
  DeltaManipulation.Scale: 0,0
  DeltaManipulation.Translation: -7,0
  CumulativeManipulation.Scale: 0,0
  CumulativeManipulation.Translation: -52,4
** Delta
  ManipulationOrigin: 154,386
  DeltaManipulation.Scale: 0,0
  DeltaManipulation.Translation: -5,0
  CumulativeManipulation.Scale: 0,0
  CumulativeManipulation.Translation: -57,4
** Delta
  ManipulationOrigin: 150,386
  DeltaManipulation.Scale: 0,0
  DeltaManipulation.Translation: -4,0
  CumulativeManipulation.Scale: 0,0
  CumulativeManipulation.Translation: -61,4
** Delta
  ManipulationOrigin: 137,386
  DeltaManipulation.Scale: 0,0
  DeltaManipulation.Translation: -13,0
  CumulativeManipulation.Scale: 0,0
  CumulativeManipulation.Translation: -74,4
** Delta
  ManipulationOrigin: 116,386
  DeltaManipulation.Scale: 0,0
  DeltaManipulation.Translation: -21,0
  CumulativeManipulation.Scale: 0,0
  CumulativeManipulation.Translation: -95,4
** Delta
  ManipulationOrigin: 114,386
  DeltaManipulation.Scale: 0,0
  DeltaManipulation.Translation: -2,0
  CumulativeManipulation.Scale: 0,0
  CumulativeManipulation.Translation: -97,4
** Completed
  ManipulationOrigin: 112,386
  TotalManipulation.Scale: 0,0
  TotalManipulation.Translation: -99,4

StartedイベントではManipulationOriginで開始位置が取得できます。
DeltaイベントではComulativeManipulation.Translationで開始位置からどれだけ移動したのかが取得できます。
CompletedイベントでManipulationOriginで終了位置が取れて、TotalManipulation.Translationで開始位置からどれだけ移動したのかが取得できます。

前にやったTouchのイベントよりも、処理しやすい値が取れてるのがわかります。Touch系のだと、自分で計算しないと、こういう値は取れませんからね。


これらのイベント引数に共通してあるプロパティとメソッドについて説明します。
StartedとDeltaイベントの引数には、Completedというメソッドがあります。このメソッドを呼ぶと、それ以降のイベントは処理されずにCompletedイベントが呼ばれて一連のイベントが終わってしまいます。タッチだけ拾って、何か処理をして、そこで終了というようなイメージのようなことをやるときに使います。

StartedとDeltaとCompletedのイベント引数に共通であるプロパティにHandledというbool型のプロパティがあります。これは、このイベントを処理したというマーカーで、自分より後にこのイベントを処理する人がいたときに処理をさせないという動きをします。
Completedメソッドとは違って、Handledをtrueにしただけでは一連のStartedとDeltaとCompletedのイベントは止まらないという点が違います。あくまで、その時の単発のイベントがほかの人に処理されなくなります。

以上、簡単にですがタッチの処理について見てみました。次は、ちょっとだけ単純なアプリケーションでも作ってみようと思います。