參考xamarin官方文檔 : https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/gestures/pan/
項目小需求:仿照ios原點實現(xiàn)在屏幕隨意拖拽和點擊
完成過程中發(fā)現(xiàn)拖拽動畫和點擊時間會沖突(安卓)
提煉官方文檔代碼 :
首先新建 blankpage 集成 ContentPage , 在構(gòu)造函數(shù)中布局 :
```
Content = new AbsoluteLayout
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Padding = new Thickness(20),
? ? ? ? ? ? ? ? Children =
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? new PanContainer
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? Content = new Image {
? ? ? ? ? ? ? ? ? ? ? ? Source = ImageSource.FromFile ("icon.jpg"),
? ? ? ? ? ? ? ? ? ? ? ? WidthRequest = 1024,
? ? ? ? ? ? ? ? ? ? ? ? HeightRequest = 768
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? };
```
自定義拖動view , 主要自定義拖動的范圍和動畫的狀態(tài)
```
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;
? ? ? ? ? ? }
? ? ? ? }
? ? }
```
以上代碼便可以實現(xiàn)一個簡單的拖拽動畫
在OnPanUpdated這個事件里面 , 分別有4種狀態(tài) , Started , Running , Completed , Canceled
Started : 手指按下去
Running : 手指移動
Completed : 收拾抬起來
Canceled : 取消 , 但是測試狀態(tài)未測到這個狀態(tài)
輸出日志 :
```
--------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
```
根據(jù)上面的輸出結(jié)果 , 我們可以根據(jù)開始時間和結(jié)束的時間差來解決手勢沖突的問題
在手勢開始的狀態(tài)記錄手指點下去的時間 , 結(jié)束時計算時間差
```
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;
```
之后我們需要在使用的時候?qū)崿F(xiàn)點擊事件 :
```
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;