Search code examples
xamarin.formstouchcoordinatesuipangesturerecognizer

Xamarin: get if a pangesture touch is inside a certain element


Is there a way to check if a touch of a pangesture is inside a certain element, like a Frame?

I added a PanGestureRecognizer to my screen. In my screen I have two Frame containing two Image. What I want is that when I move my finger on the screen I got noticed when my finger ends on one of that frames. I know how to get my finger coordinates (e.TotalX; e.TotalY;) and my thought was to check if they are inside the bounds of the frames, but I don't know how.

Any suggestion?

CODE

public MainPage()
    {
        InitializeComponent();

        var panGesture = new PanGestureRecognizer();
        panGesture.PanUpdated += PanUpdated;
        mainLayout.GestureRecognizers.Add(panGesture);

        dog = new Frame
        {
            BorderColor = Color.Blue,
            Padding = 4,
            Content = new Image
            {
                Source = ImageSource.FromResource("AccessibilityImagesSound.Immagini.dog.png"),
                Aspect = Aspect.Fill,
            },

        };
        AutomationProperties.SetIsInAccessibleTree(dog, true);
        AutomationProperties.SetName(dog, "dog");
        AbsoluteLayout.SetLayoutBounds(dog, new Rectangle(0.2, 0.5, 0.30, 0.30));
        AbsoluteLayout.SetLayoutFlags(dog, AbsoluteLayoutFlags.All);
        mainLayout.Children.Add(dog);



        cat = new Frame
        {
            BorderColor = Color.Blue,
            Padding = 4,
            Content = new Image
            {
                Source = ImageSource.FromResource("AccessibilityImagesSound.Immagini.cat.png"),
                Aspect = Aspect.Fill,
            },

        };
        AutomationProperties.SetIsInAccessibleTree(cat, true);
        AutomationProperties.SetName(cat, "cat");
        AbsoluteLayout.SetLayoutBounds(cat, new Rectangle(0.8, 0.5, 0.30, 0.30));
        AbsoluteLayout.SetLayoutFlags(cat, AbsoluteLayoutFlags.All);
        mainLayout.Children.Add(cat);

    }

    private void PanUpdated(object sender, PanUpdatedEventArgs e)
    {
        switch (e.StatusType)
        {
            case GestureStatus.Started:

                break;
            case GestureStatus.Running:

                //Here I think I have to check E.TotalX and e.TotalY

                break;
            case GestureStatus.Completed:
            case GestureStatus.Canceled: 
                break;
        }
    }

Solution

  • As far as I know the only way to get location of Touch in xamarin is through native touch gestures.

    Native gestures can be used using the Effects and this MSDocs link has full implementation of it.

    Using the TouchEffect the exact location of the touch can be fetched easily. A sample to change color of the touched frame is given below.

    XAML:

        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid.Effects>
                <touch:TouchEffect TouchAction="Grid_TouchAction"/>
            </Grid.Effects>
            <Frame
                Grid.Row="1"
                BackgroundColor="Green"
                x:Name="leftFrame"/>
            <Frame
                Grid.Row="1"
                Grid.Column="1"
                BackgroundColor="Blue"
                x:Name="rightFrame"/>
        </Grid>
    

    CS :

        private void Grid_TouchAction(object sender, TouchTracking.TouchActionEventArgs args)
        {
            switch (args.Type)
            {
                case TouchActionType.Moved:
                    if (leftFrame.Bounds.Contains(args.Location))
                    {
                        leftFrame.BackgroundColor = Color.Red;
                    }
                    else
                    {
                        leftFrame.BackgroundColor = Color.Green;
                    }
    
                    if (rightFrame.Bounds.Contains(args.Location))
                    {
                        rightFrame.BackgroundColor = Color.Red;
                    }
                    else
                    {
                        rightFrame.BackgroundColor = Color.Blue;
                    }
                    break;
            }
        }
    

    UI working:

    enter image description here

    Change the TouchAction event handler as per your requirement.