我想得到列表视图中所选项目相对于屏幕的坐标(矩形边界:x,y,宽度和高度)(假设列表视图填满整个屏幕),这样我就可以在该位置创建一个对象,动画显示我的Xamarin.Forms应用程序中所选项目的一些细节.
xaml中的listview:
<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>
Run Code Online (Sandbox Code Playgroud)
ItemTapped事件的c#代码:
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 = ...
...
}
Run Code Online (Sandbox Code Playgroud)
最终我想在带有listview的Xamarin.Forms中创建这样的东西(listview中的对象数量不同):
我创建了一个依赖项,您可以使用它来获取 iOS 和 Android 中 VisualElement 的绝对位置。我将它用于类似的目的。我们使用它来确定在列表视图中点击时要显示的弹出窗口的位置。完美运行:
依赖:
public interface ILocationFetcher
{
System.Drawing.PointF GetCoordinates(global::Xamarin.Forms.VisualElement view);
}
Run Code Online (Sandbox Code Playgroud)
iOS 实现:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
安卓实现:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
感谢@Emil,我们还有一个 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));
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
var locationFetcher = DependencyService.Get<ILocationFetcher>();
var location = locationFetcher.GetCoordinates(myVisualElement);
Run Code Online (Sandbox Code Playgroud)
确保使用依赖属性在 android 和 ios 中正确注册依赖项(请参阅https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/dependency-service/)。否则 DependencyService.Get 将返回 null。
一个快速的想法:
有一个作为单例运行的视图助手服务:
interface IViewHelper
{
Rect GetScreenCoordinates(View view);
}
Run Code Online (Sandbox Code Playgroud)
在 ListView 项模板和点击事件处理程序调用中的 AbsoluteLayout 上添加点击手势:
IViewHelper viewHelper = CrossViewHelper.Instance;
Rect rcItem = viewHelper.GetScreenCoordinates((View)sender);
Run Code Online (Sandbox Code Playgroud)
该服务的本机实现GetScreenCoordinates
做了两件事:
// Get the native view from the Xamarin Forms view
var nativeView = Platform.GetRenderer(view);
// Call native functions to get screen coordinates
Android: nativeView.GetLocationOnScreen(coords)
iOS: Use nativeView.ConvertPoint(coords, null)
Run Code Online (Sandbox Code Playgroud)
请参阅 https://forums.xamarin.com/discussion/86941/get-xy-co-ordinations-in-tap-gesture-inside-listview
另请参阅:https ://michaelridland.com/xamarin/creating-native-view-xamarin-forms-viewpage/
我没有完整的代码,但希望这可以帮助你。
我认为最后,在实现动画并显示视图之后,您可以将实现重构为可以附加到任何视图的良好行为,无论它是否在列表视图内,它都会起作用。