Pan Container 实现简单拖拽动画,防止收拾冲突

参考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;

你可能感兴趣的:(Pan Container 实现简单拖拽动画,防止收拾冲突)