参考xamarin官方文档 : https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/gestures/pan/
项目小需求:仿照ios原点实现在屏幕随意拖拽和点击
完成过程中发现拖拽动画和点击时间会冲突(安卓)
提炼官方文档代码 :
首先新建 blankpage 集成 ContentPage , 在构造函数中布局 :
```
Content = new AbsoluteLayout
{
Padding = new Thickness(20),
Children =
{
new PanContainer
{
Content = new Image {
Source = ImageSource.FromFile ("icon.jpg"),
WidthRequest = 1024,
HeightRequest = 768
}
}
}
};
```
自定义拖动view , 主要自定义拖动的范围和动画的状态
```
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);
}
private void TapedEventHander(object sender, EventArgs e)
{
}
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;
}
}
}
```
以上代码便可以实现一个简单的拖拽动画
在OnPanUpdated这个事件里面 , 分别有4种状态 , Started , Running , Completed , Canceled
Started : 手指按下去
Running : 手指移动
Completed : 收拾抬起来
Canceled : 取消 , 但是测试状态未测到这个状态
输出日志 :
```
--------start-----------03-13 01:02:38.537
--------move-----------03-13 01:02:38.553
--------move-----------03-13 01:02:38.662
--------move-----------03-13 01:02:38.692
--------end-----------03-13 01:02:44.180
```
根据上面的输出结果 , 我们可以根据开始时间和结束的时间差来解决手势冲突的问题
在手势开始的状态记录手指点下去的时间 , 结束时计算时间差
```
case GestureStatus.Started:
StartTime = DateTime.Now;
case GestureStatus.Completed:
offsetX = this.TranslationX;
offsetY = this.TranslationY;
TimeSpan timespan = DateTime.Now - StartTime;
MoveTimeSpan = timespan.Milliseconds + timespan.Seconds * 1000;
```
之后我们需要在使用的时候实现点击事件 :
```
private void TapedEventHander(object sender, EventArgs e)
{
var touchPanContainere = sender as PanContainer ;
if (touchPanContainere.MoveTimeSpan < 500)
{
todo点击事件
}
touchPanContainere.MoveTimeSpan = 0;
}
```
同时要考虑手势的范围 , 防止拖拽屏幕之外 , 我们要在移动GestureStatus.Running的时候限制动画的偏移量:
case GestureStatus.Running:
this.Content.TranslationX = e.TotalX;
if (e.TotalX+ offsetX <= -(App.Current.MainPage.Width-Width))
{
this.Content.TranslationX = -(App.Current.MainPage.Width - Width + offsetX);
}
if (e.TotalX+ offsetX >= 0)
{
this.Content.TranslationX = - offsetX;
}
this.Content.TranslationY = e.TotalY;
if (e.TotalY + offsetY <= -(App.Current.MainPage.Height - Height - 140))
{
this.Content.TranslationY = -(App.Current.MainPage.Height - Height - 140 + offsetY);
}
if (e.TotalY + offsetY >= 0)
{
this.Content.TranslationY = -offsetY;
}
break;
case GestureStatus.Completed:
offsetX += Content.TranslationX;
offsetY += Content.TranslationY;
Content.TranslationX = 0;
Content.TranslationY = 0;
this.TranslationX = offsetX;
this.TranslationY = offsetY;
TimeSpan timespan = DateTime.Now - StartTime;
MoveTimeSpan = timespan.Milliseconds + timespan.Seconds * 1000;
break;