手势基础(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呢,官方的是这样解释的:
https://img-blog.csdn.net/20131121153739828
GestureDetectorCompat实例化有下面两种方法:
https://img-blog.csdn.net/20131121154752046
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
{
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
//{
// 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
{
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());
}
}
}
结语
做到这里呢,我们就简单的实现了Xamarin下的一个手势的扩展。在使用功能的同时,可能还会遇到手势冲突等问题哈,我们会再接下来的博文继续探究手势这块的知识。