Asked by:
How can I get absolute position of element/view in xamarin.forms

Question
-
User74213 posted
I am using Xamarin Forms version 1.2.2.0.
I have a Grid with 2 rows (1st row 50pixels height) in a Page, I have a Layout Control in 2nd row of Grid.
I am working on touch gestures. I am getting X & Y of touch positions relative to MainPage(using platform specific custom renderers).
I need either touch positions relative to the Layout Control or a method to find absolute position of that Layout Control Relative to MainPage.
(Layout Control here is a Custom AbsoluteLayout Control of Xamarin.Forms)
Thanks.
Saturday, September 13, 2014 12:18 PM
All replies
-
User109780 posted
I know, it's kind of late, but I found this one as I searched for a solution for my similar problem. I just looped through all parentViews, and calculated the absolute Y. Looks like this:
var y = button.Y; var parent = button.ParentView; while (parent != null) { y += parent.Y; parent = parent.ParentView; }
Hope this helps. :)
Tuesday, December 15, 2015 11:15 AM -
User178403 posted
@ThomasUllrich it works, thanks
Thursday, December 17, 2015 2:14 PM -
User159521 posted
@ThomasUllrich said: I know, it's kind of late, but I found this one as I searched for a solution for my similar problem. I just looped through all parentViews, and calculated the absolute Y. Looks like this:
var y = button.Y; var parent = button.ParentView; while (parent != null) { y += parent.Y; parent = parent.ParentView; }
Hope this helps. :)
Nice solution Thomas :smiley:
Thursday, January 7, 2016 12:14 PM -
User109780 posted
@alessandrosuppiej Thanks :)
As far as ParentView is now deprecated I changed my code to the following:
var y = button.Y; var parent = (VisualElement)button.Parent; while (parent != null && parent.Parent.GetType() == typeof(VisualElement)) { y += parent.Y; parent = (VisualElement)parent.Parent; }
Element.Parent can be anything, like the class App. Because I know, the initial parent of my button is a VisualElement, I can cast the first time without problems. As far as I loop through the parents, I have to check for the right class type. It works for me. :)
Sunday, March 13, 2016 2:15 PM -
User159521 posted
i like pragmatic solutions like yours! we're here to work and simplify our life! not for academy!. Thanks agarin @ThomasUllrich
Sunday, March 13, 2016 2:23 PM -
User33877 posted
I am doing this in my MeasureInvalidated handler. It is called twice and the calculations for x and y are always 0 (zero). When is the best time to do this calculation?
Wednesday, May 10, 2017 11:44 PM -
User271938 posted
@"DonMesserli.1843", definitely need to do this after any layout sequence has completed. I had hoped that I could load screen coordinates for key views at the end of the main page constructor during app start-up, but no...kept getting 0 in X and Y coordinates like you. So I typically leave it until just before I need to use the information -- the coordinates are guaranteed to be accurate then.
Here's the method I use to retrieve a view's screen coordinates. Of course, since a view's X and Y coordinates are read-only properties, changing the view's location on-screen is a matter of setting its TranslationX and TranslationY properties to the difference between the proposed "new" coordinates and the view's current screen coordinates.
```csharp public (double X, double Y) GetScreenCoordinates(VisualElement view) { // A view's default X- and Y-coordinates are LOCAL with respect to the boundaries of its parent, // and NOT with respect to the screen. This method calculates the SCREEN coordinates of a view. // The coordinates returned refer to the top left corner of the view.
// Initialize with the view's "local" coordinates with respect to its parent double screenCoordinateX = view.X; double screenCoordinateY = view.Y; // Get the view's parent (if it has one...) if (view.Parent.GetType() != typeof(App)) { VisualElement parent = (VisualElement)view.Parent; // Loop through all parents while (parent != null) { // Add in the coordinates of the parent with respect to ITS parent screenCoordinateX += parent.X; screenCoordinateY += parent.Y; // If the parent of this parent isn't the app itself, get the parent's parent. if (parent.Parent.GetType() == typeof(App)) parent = null; else parent = (VisualElement)parent.Parent; } } // Return the final coordinates...which are the global SCREEN coordinates of the view return (screenCoordinateX, screenCoordinateY);
} ```
Thursday, May 25, 2017 3:01 AM -
User33877 posted
@FactoryOptimizr
I have the same code. My problem is that I want to show a bubble attached to a ViewElement as soon as the page is visible. I can't find any way to know when the page is done bing laid out.
Tuesday, May 30, 2017 3:03 PM -
User271938 posted
@"DonMesserli.1843", looks like you might be able to override the page-level "OnAppearing" event. This fires immediately before the page becomes visible, though I haven't tested to determine whether the layout manager has allocated sizes for everything on the page at that point. Another possibility might be to respond to the page's "LayoutChanged" event. If you test these options, it'd be terrific if you'd post back here about what you found.
Tuesday, May 30, 2017 7:07 PM -
User33877 posted
@FactoryOptimizr, I've tried both of those and the screen coordinates alway come back as 0,0.
Tuesday, May 30, 2017 7:50 PM -
User31385 posted
You can override the
OnElementPropertyChanged
callback and look for the relevant properties.There is also the
SizeAllocated
callback but you'll get this one multiple times and it may take a while to "settle down" to non-changing values as the layout gets calculated.Tuesday, May 30, 2017 10:51 PM -
User272571 posted
One more note about absolute position calculation. Code samples that suggests to accomulate X and Y coordinates of parent views does not handle TranslationX and TranslationY. TranslationX and TranslationY must be added to X and Y accomulators too if you want to have correct result. somethig like that:
screenCoordinateX += parent.X + parent.TranslationX; screenCoordinateY += parent.Y + parent.TranslationY;
Friday, June 9, 2017 8:54 AM -
User10329 posted
This technique does not work. If the page is inside a NavigationPage, it doesn't take into account the extra space from the navigation bar and stuff.
Wednesday, September 6, 2017 10:08 PM -
User108861 posted
I worked out a solution.
You need to ad this method to your code and use it in your renderer class.
Improtand is to call it after the constructor and OnElementChanged(..). For example in the touch of your renderer.
public static (double X, double Y) GetScreenCoordinates<TRenderer>(TRenderer renderer) where TRenderer : Android.Views.View { double screenCoordinateX = renderer.GetX(); double screenCoordinateY = renderer.GetY(); Android.Views.IViewParent viewParent = renderer.Parent; while (viewParent != null) { if (viewParent is Android.Views.ViewGroup group) { screenCoordinateX += group.GetX(); screenCoordinateY += group.GetY(); viewParent = group.Parent; } else { viewParent = null; } } return (screenCoordinateX, screenCoordinateY); }
Tuesday, April 24, 2018 8:57 AM -
User108861 posted
Update to my last post.
You can get the exact position, which also works with ScrollView, with:
renderer.GetGlobalVisibleRect(globalViewRectangle);
Tuesday, April 24, 2018 10:04 AM -
User388240 posted
I have a problem, I set the button position in the Main.Storyboard and when I start the button simulator I have a completely different place, please help :|
Monday, August 12, 2019 5:38 PM