Xamarin.Formでタッチイベントを取得した時の話

先日、Xamarinでアプリ開発をしていたとき「タッチイベント」を取得したかったのですが、少し難しい部分だったのでメモとして書き残しておきます。

今回紹介する取得方法は「タッチイベント」はクリックしたという情報だけでなく、タッチを始めた・続けている・離したといったような動作及びタッチした座標といったプラットフォーム別に取得できるような情報の取得する手段になります。

タッチした、長押ししたといった単純動作にはこの手段を使わず、OnClickイベントを使うことをお勧めします。

取得の仕方

取得した情報を入れるクラスを定義する

    public class TouchEventArgs : EventArgs
    {
        public enum TouchEventType
        {
            Entered,
            Pressed,
            Moved,
            Released,
            Exited,
            Cancelled
        }
        public TouchEventArgs(long id,TouchEventType type,Vec2 pos)
        {
            Id = id;
            Type = type;
            Pos = pos;
        }
        public long Id { get; private set; }
        public TouchEventType Type { get; private set; }
        public Vec2 Pos { get; private set; }
    }

タッチされた指の識別番号を入れるためのid(long)、タッチイベントの種類を入れるためのtype(TouchEventType)、座標情報を入れるためのPos(Forms.Vec2)を定義しました。

デリゲートを定義する

public delegate void TouchEventHundler(object obj, TouchEventArgs args);

Xamlから呼び出し用:エフェクトを定義する

    public class TEffect : RoutingEffect
    {
        public TEffect() : base("Effects.TouchEffect")
        {
        }
        public event TouchEventHundler OnTouch;
        public void OnTouchEvent(object obj,TouchEventArgs args)
        {
            OnTouch?.Invoke(obj, args);
        }
    }

Android用

[assembly: ResolutionGroupName("Effects")]
[assembly: ExportEffect(typeof(TouchEffect), "TouchEffect")]
namespace Test.Droid
{
    class TouchEffect : PlatformEffect
    {
        Android.Views.View view;
        Element element;
        TEffect tEffect;

        static Dictionary<Android.Views.View, TouchEffect> list = new Dictionary<Android.Views.View, TouchEffect>();

        protected override void OnAttached()
        {
            view = Control == null ? Container : Control;
            element = Element;
            if (view != null)
            {
                view.Touch += OnTouch;
                list.Add(view, this);
                tEffect = (TEffect)element.Effects.FirstOrDefault(e => e is TEffect);
            }
        }

        protected override void OnDetached()
        {
            if (list.ContainsKey(view))
            {
                view.Touch -= OnTouch;
                list.Remove(view);
            }
        }

        private void OnTouch(object obj, Android.Views.View.TouchEventArgs ev)
        {
                float x = ev.Event.GetX();
                float y = ev.Event.GetY();
           //ここに各イベントごとの呼び出し処理を書く tEffect.OnTouchEvent()...
        }
    }

}

このようなクラスをAndroid環境に追加します。

※iosはビルド環境がないので書きませんがGoogle上にあるのはiosの方が多いはずなのでそちらを参考にしてください~

使い方

Xaml上で使う方法

例:SkiaCanvas(SKView)上のタッチ座標を取得したいとき

        <Grid">
            <local:SKView/>
            <Grid.Effects>
                <local:TEffect OnTouch="TEffect_OnTouch"/>
            </Grid.Effects>
        </Grid>

これでOnTouch(object obj, TouchEventArgs args)が呼ばれます。

今回は同じnamespaceに書いてしまってますが、使用するときは別にしたほうがいいと思います👼

著者の一言

このホームページを始めて3か月が過ぎました(現在)。閲覧者の年齢層
が気になったのでアンケートで確認したところ同年代(大学生)の方より30,40代の方が多かったというのもあり久しぶりにちょっと専門的な事を書き始めようかななんて思った今日この頃です。


ここまで読んでくれてありがとうございました!!

ホームページでは他にも

・様々な記事や作った作品および過程
・ソースコード、素材ファイル
・あらゆる”モノ”の作り方

などなど随時、記事や作品を新規公開・更新していますので是非見ていってくださいね!見ていただけると本当に嬉しいです!