Forum Xamarin.Forms

Drag X Y Coordinates Android to Xamarin Forms

Chris001Chris001 Member ✭✭
edited December 2020 in Xamarin.Forms

Hi, I'm playing around for the first time with drag drop features in Xamarin. Basically, I'm trying to drag an image from one spot to the next.

In the Android activity I'm using the DispatchTouchEvent MotionEvent to get the RawX and RawY screed coordinates that are touched as the persons finger moves across the screen. In the Xamarin Forms for the screen I have an AbsoluteLayout that fills the screen and handled the Drop event.

The problem is the coordinates I get from Android don't seem to translate to coordinates on the xamarin forms, and when I to Image.TranslateTo( and give it the last coordinates from the android activity, it sends the image down and off the screen.

I then tried dividing the RawX and Y by the screen pixel density. This faired a little better. Now the image is on the screen but still far down at the bottom, nowhere near where my finger dropped the image. I'm missing some translation between the coordinates given to me by Android and the type of coordinate Xamarin forms is expecting. Here's what the DispatchTouchEventLooks like:

public override bool DispatchTouchEvent(MotionEvent ev)
{

        if (ev.Action == MotionEventActions.Move)
        {
            DisplayMetrics dispM = Application.Context.Resources.DisplayMetrics;

            MobileGlobals.XPointerPos = (ev.RawX / dispM.Density);
            MobileGlobals.YPointerPos = (ev.RawY / dispM.Density);

        }

        return base.DispatchTouchEvent(ev);
    }

}

Then in my form I do:

private void DropGestureRecognizer_Drop(object sender, DropEventArgs e)
{

        img.TranslateTo(MobileGlobals.XPointerPos, MobileGlobals.YPointerPos);


    }

}

Any tips are greatly appreciated.

Answers

  • LucasZhangLucasZhang Member, Xamarin Team Xamurai
    edited January 1

    In your case you could handle the drag and drop in Forms directly .

    public class PanContainer : ContentView
    {
    
        private double x, y;
        public PanContainer()
        {
            var panGesture = new PanGestureRecognizer();
    
            panGesture.PanUpdated += OnPanUpdated;
            this.GestureRecognizers.Add(panGesture);
        }
    
        private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
        {
            switch (e.StatusType)
            {
                case GestureStatus.Started:
    
    
                    break;
                case GestureStatus.Running:
    
                    Content.TranslationX = x + e.TotalX;
                    Content.TranslationY = y + e.TotalY;
    
                    break;
                case GestureStatus.Completed:
    
                    x = Content.TranslationX;
                    y = Content.TranslationY;
    
    
                    break;
            }
        }
    }
    

    in xaml

    <AbsoluteLayout>
    
    
            <local:PanContainer AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" HeightRequest="100" WidthRequest="100" >
    
                <StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
                    <Image Background="red" HeightRequest="20" WidthRequest="20" />
                </StackLayout> 
    
            </local:PanContainer>
    
        </AbsoluteLayout>
    
  • Chris001Chris001 Member ✭✭
    edited January 3

    @LucasZhang said:
    In your case you could handle the drag and drop in Forms directly .

    public class PanContainer : ContentView
    {
    
        private double x, y;
        public PanContainer()
        {
            var panGesture = new PanGestureRecognizer();
    
            panGesture.PanUpdated += OnPanUpdated;
            this.GestureRecognizers.Add(panGesture);
        }
    
        private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
        {
            switch (e.StatusType)
            {
                case GestureStatus.Started:
    
                  
                    break;
                case GestureStatus.Running:
    
                    Content.TranslationX = x + e.TotalX;
                    Content.TranslationY = y + e.TotalY;
    
                    break;
                case GestureStatus.Completed:
    
                    x = Content.TranslationX;
                    y = Content.TranslationY;
    
                   
                    break;
            }
        }
    }
    

    in xaml

    <AbsoluteLayout>
    
    
            <local:PanContainer AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" HeightRequest="100" WidthRequest="100" >
    
                <StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
                    <Image Background="red" HeightRequest="20" WidthRequest="20" />
                </StackLayout> 
    
            </local:PanContainer>
    
        </AbsoluteLayout>
    

    So, I just got around to trying this and ran into an issue. Even though I added a local reference:

    xmlns:local="clr-namespace: MyApp;assembly=MyApp"

    added your class, then added the panel to my form:

    When I build it keeps telling me "Cannot resolve type "local:PanContainer"... even though it's there, in the same namespace, and it's properties populate in the xaml editor and as you see above in my xaml content page header I included the reference to local in my namespace... so... have to figure out what I'm missing to get this to build. Here's what the form looks like:

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:local="clr-namespace: MyApp;assembly=MyApp"
                 x:Class="MyApp.MainPage">
        <AbsoluteLayout x:Name="absScreenLayout" AutomationId="absScreenLayout" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
            <AbsoluteLayout.GestureRecognizers>
                <DropGestureRecognizer AllowDrop="true" DragOver="DropGestureRecognizer_DragOver" Drop="DropGestureRecognizer_Drop"/>
            </AbsoluteLayout.GestureRecognizers>
            <local:PanContainer AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
    </local:PanContainer>
        </AbsoluteLayout>
    </ContentPage>
    

    and the pan contain class looks like:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Xamarin.Forms;
    
    namespace MyApp~~~~
    {
        public class PanContainer : ContentView
        {
            private double x = 0;
            private double y = 0;
            public double XCoord { get => x; set => x = value; }
            public double YCoord { get => y; set => y = value; }
    
            public PanContainer()
            {
                var panGesture = new PanGestureRecognizer();
                panGesture.PanUpdated += OnPanUpdated;
                this.GestureRecognizers.Add(panGesture);
            }
    
            private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
            {
                switch (e.StatusType)
                {
                    case GestureStatus.Started:
                        break;
                    case GestureStatus.Running:
                        Content.TranslationX = x + e.TotalX;
                        Content.TranslationY = y + e.TotalY;
                        break;
                    case GestureStatus.Completed:
                        x = Content.TranslationX;
                        y = Content.TranslationY;
                        break;
                }
            }
        }
    }
    
    
  • Chris001Chris001 Member ✭✭

    @LucasZhang said:
    Could you share your sample so that I can test it on my side ?

    I think this is some issue with the platform as it does it with any local derived xamarin control class I try to add to any project. I'm re-installing VS Community 2019 to see if it fixes the issue.

  • Chris001Chris001 Member ✭✭
    edited January 5

    @Chris001 said:

    @LucasZhang said:
    Could you share your sample so that I can test it on my side ?

    I think this is some issue with the platform as it does it with any local derived xamarin control class I try to add to any project. I'm re-installing VS Community 2019 to see if it fixes the issue.

    Well... that didn't work. Same problem. I need to get past this. It recognizes the class in the intellisense, but it just keeps giving me the error:

    XFC0000 Cannot resolve type "local:MyEntry".

    In this case I created another class that derives from Entry to see if it would be any different and same deal. Everything is updated. I'm on the latest nuget package for Xamarin forms, latest for Essentials. Latest updates for VS 2019. Not sure what the heck is going on. I created a completely new project, gave it a really short name (in case there is some path length issue), put it on the root of my c drive, and same issue.

  • LucasZhangLucasZhang Member, Xamarin Team Xamurai

    xmlns:local="clr-namespace: YOUR PROJECT NAME;assembly=YOUR PROJECT NAME

  • Chris001Chris001 Member ✭✭

    @LucasZhang said:
    xmlns:local="clr-namespace: YOUR PROJECT NAME;assembly=YOUR PROJECT NAME

    How is that different from what I did, other than you left off the end quote?

    xmlns:local="clr-namespace: MyApp;assembly=MyApp"

    My test app is called MyApp and the assembly builds a dll of that same name.

  • LucasZhangLucasZhang Member, Xamarin Team Xamurai

    Could you share your sample so that I can test it on my side ?

  • Chris001Chris001 Member ✭✭

    @LucasZhang said:
    Could you share your sample so that I can test it on my side ?

    Here's a zip file of the small test project.

  • Chris001Chris001 Member ✭✭

    @LucasZhang said:
    Could you share your sample so that I can test it on my side ?

    Any clues what might be missing?

  • Chris001Chris001 Member ✭✭

    @LucasZhang said:
    Could you share your sample so that I can test it on my side ?

    Update: I tried creating a new project and using a "Tabbed" template instead of a bland template and this time the project appears to deal with local objects correctly. Odd. Wonder what the diff is?

  • LucasZhangLucasZhang Member, Xamarin Team Xamurai

    I will check it as soon as possible .

  • Chris001Chris001 Member ✭✭
    edited January 14

    @LucasZhang said:
    I will check it as soon as possible .

    I got the pan gesture recognizer working, and I can use it to move around a single item, but if I have several items on a surface under it, I want to be able to detect exactly where the finger is touching and whether it is in proximity. However, it appears it does not return x/y coordinates, such as the starting position where the finger touches the surface in order to detect proximity if the finger is touching an object underneath the panel in order to drag that item. It returns only x/y offset from the drag operation and simply translates whatever object you want to translate by those x/y offsets. I need to get real coordinates of where the finger is touching to be able to handle dragging around multiple objects independently.

  • LucasZhangLucasZhang Member, Xamarin Team Xamurai

    Since the pan gesture recognizer is working . You could create a new thread with more details about the new issue so that I can help you better .

  • Chris001Chris001 Member ✭✭

    @LucasZhang said:
    Since the pan gesture recognizer is working . You could create a new thread with more details about the new issue so that I can help you better .

    Even though the pan container works in the sense that it will move a single object around that is sitting within it, I'm still in the same boat. given multiple images or objects on screen, I need to get the x/y coordinates of any item that is touched and be able to drag it to any other x/y coordinate, get the coordinate where the finger drag stopped, and move the item to that spot on the screen. I can't close this thread until that problem is solved. I'll investigate more options today and close the thread when the problem is solved. Let me know if you have more ideas.

  • Chris001Chris001 Member ✭✭

    I found another solution called SkiaSharp provided by Microsoft via Nuget that appears to work well. Github has example projects.

Sign In or Register to comment.