I want to get the coordinates (rectangle bounds: x, y, width and height) of the selected item in the listview relative to the screen (assume the listview fills the whole screen), so that I can create an object at that location and animate it to display some details of the selected item in my Xamarin.Forms app.
listview in xaml:
<ListView ItemTapped="ItemTapped"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0.5, 0.5, 1.0, 1.0">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="50">
<AbsoluteLayout>
<Label Text="{Binding Info}"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0.1, 0.5, 0.7, 0.5"/>
</AbsoluteLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
c# code for ItemTapped event:
void ItemTapped(object sender, EventArgs args)
{
var listView = (ListView)sender; // the listview
var selectedItem = args.Item; // the selected item
// need to get selected item coordinates for the animation
var selectedItemBounds = ...
...
}
Eventually I want to create somehting like this in Xamarin.Forms with a listview (the number of objects in the listview varies):
I've created a dependency you can use to get the absolute position of a VisualElement in iOS and Android. I use it for a similar purpose. We use it to determine the position of a popup to show when tapping in the listview. Works perfectly:
Dependency:
public interface ILocationFetcher
{
System.Drawing.PointF GetCoordinates(global::Xamarin.Forms.VisualElement view);
}
iOS Implementation:
class LocationFetcher : ILocationFetcher
{
public System.Drawing.PointF GetCoordinates(global::Xamarin.Forms.VisualElement element)
{
var renderer = Platform.GetRenderer(element);
var nativeView = renderer.NativeView;
var rect = nativeView.Superview.ConvertPointToView(nativeView.Frame.Location, null);
return new System.Drawing.PointF((int)Math.Round(rect.X), (int)Math.Round(rect.Y));
}
}
Android Implementation:
class LocationFetcher : ILocationFetcher
{
public System.Drawing.PointF GetCoordinates(global::Xamarin.Forms.VisualElement element)
{
var renderer = Platform.GetRenderer(element);
var nativeView = renderer.View;
var location = new int[2];
var density = nativeView.Context.Resources.DisplayMetrics.Density;
nativeView.GetLocationOnScreen(location);
return new System.Drawing.PointF(location[0] / density, location[1] / density);
}
}
Thanks to @Emil we also have an UWP implementation:
public System.Drawing.PointF GetCoordinates(global::Xamarin.Forms.VisualElement element)
{
var renderer = Xamarin.Forms.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));
}
usage example:
var locationFetcher = DependencyService.Get<ILocationFetcher>();
var location = locationFetcher.GetCoordinates(myVisualElement);
Be sure to properly register the dependency correctly (see https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/dependency-service/ ) in the android and ios using the dependency attribute. Otherwise the DependencyService.Get will return null.
PaulVrugt's answer perfectly works for IOS and Android. Just to extend his implementation for anyone requires also UWP.
public System.Drawing.PointF GetCoordinates(global::Xamarin.Forms.VisualElement element)
{
var renderer = Xamarin.Forms.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));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With