Xamarin: как получить координаты курсора / касания (позиции X и Y)?

Вступление

Я создаю свое первое приложение Xamarin (сначала оно будет нацелено на UWP, затем на Android, наконец, на iOS).

По сути, приложение должно обнаружить несколько пальцев, и круги будут появляться на каждом пальце и следовать за ними.

Мое приложение

Сначала я подумал, что пользовательский интерфейс и графика не могут быть закодированы с помощью Xamarin, поэтому я начал код UWP:

MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Windows.Input;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.Devices.Input;
using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;
using Windows.UI.Input;
using Windows.UI.Xaml.Shapes;
using Windows.UI;

namespace App1.UWP
{
    public sealed partial class MainPage
    {
        public MainPage()
        {
            this.InitializeComponent();

            LoadApplication(new App1.App());
        }

        private async void OnPointerPressed(object sender, PointerRoutedEventArgs e)
        {
            Debug.WriteLine(e.Pointer.PointerDeviceType + " " + sender + " " + e);

            Point pointerPos = e.GetCurrentPoint(rootPanel).Position;

            Debug.WriteLine(pointerPos.X + " " + pointerPos.Y);

            Ellipse ellipse1 = new Ellipse();
            ellipse1.Fill = new SolidColorBrush(Colors.SteelBlue);
            ellipse1.Width = 100;
            ellipse1.Height = 100;
            //ellipse1.Margin.Left = pointerPos.X + 50;
            //ellipse1.Margin.Top = pointerPos.Y + 50;

            rootPanel.Children.Add(ellipse1);
            Debug.WriteLine(rootPanel.Children.Count);

            switch (e.Pointer.PointerDeviceType)
            {
                case PointerDeviceType.Touch:
                    break;
                case PointerDeviceType.Pen:
                    break;
                case PointerDeviceType.Mouse:

                    ContentDialog noMouseAvaliableDialog = new ContentDialog()
                    {
                        Title = "Erreur de méthode d'entrée",
                        Content = "Il est impossible de savoir qui va jouer en premier aver un joueur :(\n Veuillez essayer avec le clavier.",
                        PrimaryButtonText = "OK chef"
                    };

                    await noMouseAvaliableDialog.ShowAsync();
                    break;
                default:
                    break;
            }

            Debug.WriteLine("-------------------------");
        }
    }
}

MainPage.xaml

<forms:WindowsPage
    x:Class="App1.UWP.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:forms="using:Xamarin.Forms.Platform.UWP"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1.UWP"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    PointerPressed="OnPointerPressed">

    <RelativePanel
        Name="rootPanel"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
        HorizontalAlignment="Stretch"
        VerticalAlignment="Stretch">

    </RelativePanel>
</forms:WindowsPage>

Как видите, я могу получить координаты X и Y курсора, НО мой эллипс не отображается. Поэтому я заметил, что Xamarin xaml выиграл вместо моего UWP xaml.

Поэтому я попробовал еще раз с Xamarin. Я искал общий код графического API, я нашел SkiaSharp. И мой эллипс появляется в коде Xamarin:

MainPage.xaml.cs

using SkiaSharp;
using SkiaSharp.Views.Forms;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace App1
{
    public partial class MainPage : ContentPage
    {
        private static SKCanvas canvas;

        public MainPage()
        {
            InitializeComponent();
        }

        private void OnPainting(object sender, SKPaintSurfaceEventArgs e)
        {
            canvas = e.Surface.Canvas;
        }

        private void onTapGestureRecognizerTapped(object sender, EventArgs e)
        {
            Debug.WriteLine("Tapped !!!!!");
            //((TappedEventArgs) e).
        }

        /*private void onPanUpdated(object sender, PanUpdatedEventArgs e)
        {
            Debug.WriteLine("Panned !!!!!" + e.TotalX + " " + e.TotalY);
        }*/

        internal void drawCircleOnCanvas(Point pointerPos, int radius)
        {
            Debug.WriteLine(pointerPos.X + " " + pointerPos.Y);

            SKPaint circleFill = new SKPaint
            {
                IsAntialias = true,
                Style = SKPaintStyle.Fill,
                Color = SKColors.AliceBlue
            };
            canvas.DrawCircle(((float) pointerPos.X - 50), ((float) pointerPos.Y - 50), radius, circleFill);
        }
    }
}

MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:App1"
             x:Class="App1.MainPage"
             xmlns:views="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms">

    <Label Text="Ooooh, you touch my tralala" 
           VerticalOptions="Center" 
           HorizontalOptions="Center" />

    <!--<relativelayout
        x:Name="rootPanel" 
        backgroundcolor="lime"
        horizontaloptions="fill"
        verticaloptions="fill">

    </relativelayout>-->

    <Grid>
        <views:SKCanvasView PaintSurface="OnPainting"/>
        <Grid.GestureRecognizers>
            <TapGestureRecognizer
                Tapped="onTapGestureRecognizerTapped"
                NumberOfTapsRequired="1"/>
            <!--<PanGestureRecognizer PanUpdated="onPanUpdated"/> -->
        </Grid.GestureRecognizers>
    </Grid>

</ContentPage>

Наконец, для каждой точки касания остаются только положения X и Y, на которых я рисую мои эллипсы. Как видите, я смотрел по-разному: TapGestureRecognizer, PanGestureRecognizer...

Но я не мог получить эти координаты.

Я нашел API MR.Gestures, но он лицензируется для каждого имени приложения.

Вопросы

Итак, я прошу опытных людей:

  • Предоставляет ли Xamarin API сенсорной позиции / жестов?
  • Является ли MR.Gestures лучшим решением для прикосновения?
  • Существуют ли другие сенсорные API с общим кодом?

Или просто, как я могу получить координаты всех точек касания с Xamarin?

Спасибо

PS: я нахожу эту статью, когда пишу этот стек, читая...

1 ответ

Решение

Предоставляет ли Xamarin API сенсорной позиции / жестов?

К сожалению, нет! Единственное, что вы можете сделать с Xamarin, это использовать TapGestureRecognizer, PinchGestureRecognizer или же PanGestureRecognizer класс, как вы упомянули, но это все. Ни один из них не даст вам координаты х / у.

Является ли MR.Gestures лучшим решением для прикосновения?

Я столкнулся с такой же проблемой. Если вы не хотите изобретать велосипед, вам обязательно нужно использовать внешний API.

Мистер Жестурс делает эту работу довольно хорошо. К сожалению, я не слышал ни о каком бесплатном API. Как вы уже упоминали, это приложение лицензируется:(

Или просто, как я могу получить координаты всех точек касания с Xamarin?

Вы должны реализовать собственные средства визуализации для каждой платформы (или UWP в вашем случае). Это то, что Mr.Gestures делает для вас за кулисами. Если вы не хотите реализовывать это самостоятельно, в настоящее время единственным вариантом является использование внешнего API.

Может быть, однажды Xamarin предоставит такой API прямо из коробки... Давайте не будем скучать!

Надеюсь это поможет!

Поздно, но если вы используете Skia, вы можете добавить этот Nuget:
https://github.com/OndrejKunc/SkiaScene

Вы сможете отслеживать свою позицию касания внутри сцены.

Другие вопросы по тегам