1. 程式人生 > >在 Xamarin.Form 下擴充套件手勢

在 Xamarin.Form 下擴充套件手勢

一 手勢基礎(Android & iOS)

> Andorid手勢基礎

當用戶觸控式螢幕幕時會產生很多的觸控事件,down、up、move等等。View類有個View.OnTouchListener內部介面,通過重寫他的onTouch(View v, MotionEvent event)方法,我們可以處理一些touch事件,如下:

[java] view plain copy

print?

public class MainActivity extends Activity {  

...  

// This example shows an Activity, but you would use the same approach if  

// you were subclassing a View.  

@Override  

public boolean onTouchEvent(MotionEvent event){   

    int action = MotionEventCompat.getActionMasked(event);  

    switch(action) {  

        case (MotionEvent.ACTION_DOWN) :  

            Log.d(DEBUG_TAG,"Action was DOWN");  

            return true;  

        case (MotionEvent.ACTION_MOVE) :  

            Log.d(DEBUG_TAG,"Action was MOVE");  

            return true;  

        case (MotionEvent.ACTION_UP) :  

            Log.d(DEBUG_TAG,"Action was UP");  

            return true;  

        case (MotionEvent.ACTION_CANCEL) :  

            Log.d(DEBUG_TAG,"Action was CANCEL");  

            return true;  

        case (MotionEvent.ACTION_OUTSIDE) :  

            Log.d(DEBUG_TAG,"Movement occurred outside bounds " +  

                    "of current screen element");  

            return true;        

        default :   

            return super.onTouchEvent(event);  

    }        

}  

    OnTouch提供的事件還是相對較簡單,如果需要處理一些複雜的手勢,用這個介面就會很麻煩,因為我們要根據使用者觸控的軌跡去判斷是什麼手勢。Android sdk給我們提供了GestureDetector(Gesture:手勢Detector:識別)類,通過這個類我們可以識別很多的手勢。

public class GestureDetector extends Object    

Java.lang.Object

android.view.GestureDetector

  GestureDetector屬於android.view包,android還提供了android.gesture包支援更多的手勢操作,以後我們會介紹到。官方的介紹中使用了GestureDetectorCompat處理手勢識別,為什麼使用GestureDetectorCompat替換了GestureDetector呢,官方的是這樣解釋的:

 GestureDetectorCompat例項化有下面兩種方法:

GestureDetector

GestureDetector類對外提供了兩個介面:OnGestureListener,OnDoubleTapListener,還有一個內部類SimpleOnGestureListener;SimpleOnGestureListener類是GestureDetector提供給我們的一個更方便的響應不同手勢的類,它實現了上述兩個介面,該類是static class,也就是說它實際上是一個外部類,我們可以在外部繼承這個類,重寫裡面的手勢處理方法。因此實現手勢識別有兩種方法,一種實現OnGestureListener介面,另一種是使用SimpleOnGestureListener類。

OnGestureListener有下面的幾個動作:

按下(onDown): 剛剛手指接觸到觸控式螢幕的那一剎那,就是觸的那一下。

拋擲(onFling): 手指在觸控式螢幕上迅速移動,並鬆開的動作。

長按(onLongPress): 手指按在持續一段時間,並且沒有鬆開。

滾動(onScroll): 手指在觸控式螢幕上滑動。

按住(onShowPress): 手指按在觸控式螢幕上,它的時間範圍在按下起效,在長按之前。

擡起(onSingleTapUp):手指離開觸控式螢幕的那一剎那。

  使用OnGestureListener介面,這樣需要過載OnGestureListener介面所有的方法,適合監聽所有的手勢,正如官方文件提到的“Detecing All Supported Gestures

=========================================================================

>iOS 手勢基礎

UIGestureRecognize手勢識別器的使用簡介

手勢識別器是一個抽象類, 特殊的觸控事件. 我們不使用它本身,而是使用它的子類

型別

類 名

平移

UIPanGestureRecognizer

輕掃(滑動)

UISwipeGestureRecognizer

長按

UILongPressGestureRecognizer

捏合

UIPinchGestureRecognizer

旋轉

UIRotationGestureRecognizer

輕拍

UITapGestureRecognizer

二 實戰(ps:下面以自定義以為XF定義以隨便一個手勢為例:)

XF部分:

using System;

using Xamarin.Forms;

namespace KKMobile.Control

{

public class LongPressMaskingView : Xamarin.Forms.Grid

{

public event EventHandler LongPressActivated;

public event EventHandler LongPressEnd;

public event EventHandler TapUPed;

public LongPressMaskingView()

{

}

public void HandTapUped(object sender, EventArgs e)

{

Device.BeginInvokeOnMainThread(() =>

{

if (TapUPed != null)

{

TapUPed(this, new EventArgs());

}

});

}

public void HandleLongPress_End(object sender, EventArgs e)

{

Device.BeginInvokeOnMainThread(() =>

{

if (LongPressEnd != null)

{

LongPressEnd(this, new EventArgs());

}

});

}

public void HandleLongPress(object sender, EventArgs e)

{

Device.BeginInvokeOnMainThread(() =>

{

if (LongPressActivated != null)

{

System.Diagnostics.Debug.WriteLine("HandleLongPress");

LongPressActivated(this, new EventArgs());

}

});

}

#region 繫結手勢

// public static readonly BindableProperty TappedCommandProperty =

//BindableProperty.Create(nameof(TappedCommand),

// typeof(ICommand),

// typeof(LongPressGerCachImage),

// default(ICommand));

// public ICommand TappedCommand

// {

// get { return (ICommand)GetValue(TappedCommandProperty); }

// set { SetValue(TappedCommandProperty, value); }

// }

// public static readonly BindableProperty LongPressCommandProperty =

// BindableProperty.Create(nameof(LongPressCommand),

// typeof(ICommand),

// typeof(LongPressGerCachImage),

// default(ICommand));

// public ICommand LongPressCommand

// {

// get { return (ICommand)GetValue(LongPressCommandProperty); }

// set { SetValue(LongPressCommandProperty, value); }

// }

// public LongPressGerCachImage() { }

#endregion

}

}

===============================================================================

Xamarin.iOS 實現

using System;

using Foundation;

using UIKit;

using Xamarin.Forms.Platform.iOS;

using Xamarin.Forms;

using KKMobile.Control;

using KKMobile.iOS.Renderer;

[assembly: ExportRenderer(typeof(LongPressMaskingView), typeof(LongPressMaskingViewRenderer))]

namespace KKMobile.iOS.Renderer

{

public class LongPressMaskingViewRenderer : ViewRenderer

{

LongPressMaskingView view;

UILongPressGestureRecognizer longPressGer { get; set; }

UITapGestureRecognizer TapGer { get; set; }

public LongPressMaskingViewRenderer()

{

longPressGer = new UILongPressGestureRecognizer((longPress) =>

{

if (longPress.State == UIGestureRecognizerState.Began)

{

view.HandleLongPress(view, new EventArgs());

}

if (longPress.State == UIGestureRecognizerState.Ended)

{

view.HandleLongPress_End(view, new EventArgs());

}

})

{ MinimumPressDuration = 0.5, NumberOfTouchesRequired = 1 };

//**

TapGer = new UITapGestureRecognizer((Tap) =>

{

if (Tap.State == UIGestureRecognizerState.Ended)

{

view.HandTapUped(view,new EventArgs());

}

}) { };

this.AddGestureRecognizer(TapGer);

this.AddGestureRecognizer(longPressGer);

}

protected override void OnElementChanged(ElementChangedEventArgs<View> e)

{

base.OnElementChanged(e);

if (e.NewElement != null)

{

view = e.NewElement as LongPressMaskingView;

}

if (e.NewElement == null)

{

if (longPressGer != null)

{

this.RemoveGestureRecognizer(longPressGer);

}

}

if (e.OldElement == null)

{

this.AddGestureRecognizer(longPressGer);

}

}

//UITapGestureRecognizer tapGesturesRecognizer;

//UILongPressGestureRecognizer longPressGesturesRecognizer;

//protected override void OnElementChanged(ElementChangedEventArgs<View> e)

//{

// base.OnElementChanged(e);

// tapGesturesRecognizer = new UITapGestureRecognizer(() =>

// {

// var grid = (LongPressGerCachImage)Element;

// if (grid.TappedCommand.CanExecute(Element.BindingContext))

// {

// grid.TappedCommand.Execute(Element.BindingContext);

// }

// });

// longPressGesturesRecognizer = new UILongPressGestureRecognizer(() =>

// {

// var grid = (LongPressGerCachImage)Element;

// if (longPressGesturesRecognizer.State == UIGestureRecognizerState.Ended &&

// grid.LongPressCommand.CanExecute(Element.BindingContext))

// {

// grid.LongPressCommand.Execute(Element.BindingContext);

// }

// });

// this.RemoveGestureRecognizer(tapGesturesRecognizer);

// this.RemoveGestureRecognizer(longPressGesturesRecognizer);

// this.AddGestureRecognizer(tapGesturesRecognizer);

// this.AddGestureRecognizer(longPressGesturesRecognizer);

//}

}

}

-----------

===============================================================================

Xamarin.Android實現

一》先建立一個手勢事件監聽類

sing System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Android.App;

using Android.Content;

using Android.OS;

using Android.Runtime;

using Android.Views;

using Android.Widget;

namespace KKMobile.Droid.Renderer

{

public class FancyGestureListener : GestureDetector.SimpleOnGestureListener

{

public event EventHandler HandTapUped;

public override bool OnSingleTapUp(MotionEvent e) //擡起(onSingleTapUp):手指離開觸 摸屏的那一剎那。

{

HandTapUped(this, null);

return true;

}

}

}

二》建立安卓手勢Render類

using Xamarin.Forms.Platform.Android;

using Xamarin.Forms;

using Android.Views;

using KKMobile.Droid.Renderer;

using KKMobile.Control;

using System;

[assembly: ExportRenderer(typeof(LongPressMaskingView), typeof(LongPressMaskingViewRenderer_Droid))]

namespace KKMobile.Droid.Renderer

{

public class LongPressMaskingViewRenderer_Droid : ViewRenderer

{

LongPressMaskingView _longPressMaskingView;

private readonly FancyGestureListener _listener;

private readonly GestureDetector _detector;

public LongPressMaskingViewRenderer_Droid()

{

_listener = new FancyGestureListener();

_detector = new GestureDetector(_listener);

}

protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)

{

base.OnElementChanged(e);

if (e.NewElement != null)

{

_longPressMaskingView = e.NewElement as LongPressMaskingView;

}

if (e.NewElement == null)

{

this.GenericMotion -= HandleGenericMotion;

this.Touch -= HandleTouch;

//_listener.HandleLongPress -= OnHandLongPress;

//_listener.HandLongPressEnded -= OnHandLongPressEnded;

_listener.HandTapUped -= OnHandTapUped;

}

if (e.OldElement == null)

{

this.GenericMotion += HandleGenericMotion;

this.Touch += HandleTouch;

//_listener.HandleLongPress += OnHandLongPress;

//_listener.HandLongPressEnded += OnHandLongPressEnded;

_listener.HandTapUped += OnHandTapUped;

}

}

void HandleTouch(object sender, TouchEventArgs e)

{

Console.WriteLine("====="+e.Event.Action);

try

{

_longPressMaskingView = this.Element as LongPressMaskingView;

if (e.Event.Action == MotionEventActions.Down)

{

Console.WriteLine(e.Event.Action);

_longPressMaskingView.HandleLongPress(this, new System.EventArgs());

Console.WriteLine("--down--");

}

if (e.Event.Action == MotionEventActions.Up || e.Event.Action == MotionEventActions.Cancel)

{

Console.WriteLine(e.Event.Action);

_longPressMaskingView.HandleLongPress_End(this, new System.EventArgs());

Console.WriteLine("--up--");

}

_detector.OnTouchEvent(e.Event);

}

catch (Exception ex) {

}

}

void HandleGenericMotion(object sender, GenericMotionEventArgs e)

{

_detector.OnTouchEvent(e.Event);

}

void OnHandTapUped(object sender, EventArgs e)

{

_longPressMaskingView = this.Element as LongPressMaskingView;

_longPressMaskingView.HandTapUped(this, new System.EventArgs());

}

}

}