mauimaui-windows

How to get MAUI UI element absolute coordinates


I'm developping a MAUI app and I want to show a popup at the coordinates of the button that initiated it. The code for generating the popup at the given coordinates works fine (using an absolute layout), but I'm having a hard time acquiring the coordinates.

The code from the following URL worked flawlessly in Xamarin, but it doesn't work in MAUI.

How to get coordinates of the selected item in a list view in Xamarin.Forms?

This is my Xamarin version of what the first link suggests.

var renderer = xForms.Platform.UWP.Platform.GetRenderer(element);
var nativeView = renderer.GetNativeElement();
var element_Visual_Relative = nativeView.TransformToVisual(Window.Current.Content);
Point point = element_Visual_Relative.TransformPoint(new Point(0, 0));
return new System.Drawing.PointF((int)Math.Round(point.X), (int)Math.Round(point.Y));

And this is my attempt at converting it to MAUI. It returns 0, 0.

var frameworkElement = element.ToPlatform(MauiProgram.Context);
var platformView = (Microsoft.UI.Xaml.Window)App.Windows.First().Handler.PlatformView;
var visualRelativePoint = frameworkElement.TransformToVisual(platformView.Content);
var point = visualRelativePoint.TransformPoint(new Windows.Foundation.Point(0, 0));
return new Point((int)Math.Round(point.X), (int)Math.Round(point.Y));

Is someone versed enough in Maui to tell me what's wrong? I plan a release on WinUI, but input for other platforms, I'm sure, would be useful to all.

Thank you very much

P-S: Here's another solution, but it's very basic and doesn't handle list view items:

Get Elements position relative to screen in Xamarin

Update:

I tried @Liyun Zhang - MSFT's solution and it works! I revamped it to take into account navbar height, which appears to be applied systematically to coordinates event if it's invisible. Here's my latest version.

using uiXaml = Microsoft.UI.Xaml;

public override Point GetElementCoordinates(VisualElement element){
    var nativeWindow = (uiXaml.Window)App.Current.Windows.First().Handler.PlatformView;
    var nativeElement = (uiXaml.UIElement)element.Handler.PlatformView;
    var coordinates = nativeElement .TransformToVisual(nativeWindow.Content)
                                    .TransformPoint(new Windows.Foundation.Point(0, 0));

    var navBarHeight = (App.Current.MainPage is NavigationPage navPage && navPage.CurrentPage != null) 
                     ? navPage.Height - navPage.CurrentPage.Height : 0;

    return new Point((int)Math.Round(coordinates.X), 
                     (int)Math.Round(coordinates.Y - navBarHeight));
}

Solution

  • First of all, there are two properties name X and Y for the maui's control. You can get it with the code such as: button.X or button.Y.

    In addition, I have tried your code about getting the absolute coordinates and changed a little.

    Microsoft.UI.Xaml.Window window = (Microsoft.UI.Xaml.Window)App.Current.Windows.First<Window>().Handler.PlatformView;
    var platformview = CounterBtn.Handler.PlatformView as Microsoft.Maui.Platform.MauiButton;
    var point = platformview.TransformToVisual(window.Content).TransformPoint(new Windows.Foundation.Point(0, 0));
    

    The platformview is a button and the point will get a value with X, Y different from the button.X or button.Y.