Search code examples
xamarin.formsandroid-animationuigesturerecognizeruipangesturerecognizer

PanGestureRecognizer sporadic during drag


I'm creating a simple drag animation to an image using PanGestureRecognizer. However, when the drag is in progress the TotalX and TotalY values are not consistent, they seem to jump / flicker / flutter between 2 values as I drag. Below is a raw trace example of the values:

[0:] PanUpdated: StatusType: Started, GestureId: 0, TotalX: 0, TotalY: 0
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 11.1617584228516, TotalY: 11.9234619140625
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 2.45475260416667, TotalY: 2.80341593424479
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 11.8422292073568, TotalY: 12.5428161621094
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 3.20952860514323, TotalY: 3.77924601236979
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 12.6615346272786, TotalY: 13.5227355957031
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 4.03237915039063, TotalY: 4.76089477539063
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 12.8976643880208, TotalY: 14.1595052083333
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 4.93493143717448, TotalY: 5.72846476236979
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 13.551747639974, TotalY: 14.7833862304688
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 5.67492167154948, TotalY: 6.68665568033854
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 14.1307627360026, TotalY: 15.5877075195313
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 6.67552185058594, TotalY: 7.82212320963542
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 14.8915608723958, TotalY: 16.3966369628906
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 7.67821248372396, TotalY: 8.44764200846354
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 15.2916819254557, TotalY: 16.9883219401042
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 8.57093811035156, TotalY: 9.37423706054688
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 15.8519948323568, TotalY: 17.2493794759115
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 9.13496907552083, TotalY: 10.1264038085938
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 16.5894927978516, TotalY: 17.6655578613281
[0:] PanUpdated: StatusType: Running, GestureId: 0, TotalX: 10.049072265625, TotalY: 11.0558268229167
[0:] PanUpdated: StatusType: Completed, GestureId: 0, TotalX: 0, TotalY: 0

If however I add the gesture to the container the value flows fine.

Here is my page:

<ContentPage>
    <AbsoluteLayout >
        <Image x:Name="Card" Source="CardBack_Red.png" />
    </AbsoluteLayout>
</ContentPage>

And the code behind:

    public partial class MainPage : ContentPage
    {
        double x, y;

        public MainPage()
        {
            InitializeComponent();

            var panGesture = new PanGestureRecognizer();
            panGesture.PanUpdated += PanGesture_PanUpdated;
            panGesture.TouchPoints = 1;
            Card.GestureRecognizers.Add(panGesture);
        }

        private void PanGesture_PanUpdated(object sender, PanUpdatedEventArgs e)
        {
            Debug.WriteLine($"PanUpdated: StatusType: {e.StatusType}, GestureId: {e.GestureId}, TotalX: {e.TotalX}, TotalY: {e.TotalY}");

            Image card = (Image)sender;

            switch (e.StatusType)
            {
                case GestureStatus.Started:
                    x = card.TranslationX;
                    y = card.TranslationY;
                    break;
                case GestureStatus.Running:
                    card.TranslationX = x + e.TotalX;
                    card.TranslationY = y + e.TotalY;
                    break;
            }
        }
    }
}

Seems like I'm fighting something but I don't know what, any ideas?

Thanks

-John


Solution

  • SOLVED

    Turns out I simply had the wrong translation algorithm, the GestureStatus.Running case needed to add the delta directly to the image translation coordinates, instead of also adding the starting translation. The case in my code above no looks like this:

            case GestureStatus.Running:
                dragCard.TranslationX += e.TotalX;
                dragCard.TranslationY += e.TotalY;
                break;
    

    I found a munch better sample here, helped a lot.