这是我的XAML。这个ContentView
在一个AbsoluteLayout
里面,但我认为这无关紧要。这个想法是有一个列表视图的框架,周围有一个深色的背景。如果用户在Frame
之外点击,我想收到Overlay_Tapped
。
在iOS中,永远不会调用SpinnerList_ItemSelected
。相反,即使用户在Frame
内部单击,Overlay_Tapped
也是。在安卓系统中,一切都很好。
我尝试在Frame
、ListView
甚至ViewCell
中设置InputTransparent="False"
。没有帮助。帮助的是在TapGestureRecognizer
中设置NumberOfTapsRequired="2"
,但这显然不是我的意图。
帮助?
<ContentView
x:Name="SpinnerOverlay"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
IsVisible="False"
InputTransparent="False"
BackgroundColor="{x:Static engine:LmcColor.overlay}">
<Frame
OutlineColor="Black"
Padding="10,10,10,10"
BackgroundColor="White"
HorizontalOptions="Center"
VerticalOptions="Center">
<ListView
x:Name="SpinnerList"
HorizontalOptions="Center"
VerticalOptions="Center"
HasUnevenRows="False"
SeparatorColor="Transparent"
ItemSelected="SpinnerList_ItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ContentView
Padding="5,0,5,0"
BackgroundColor="{Binding BackColor}">
<Label
Text="{Binding ItemText}"
Style="{StaticResource StandardStyle}"/>
</ContentView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Frame>
<ContentView.GestureRecognizers>
<TapGestureRecognizer Tapped="Overlay_Tapped"/>
</ContentView.GestureRecognizers>
</ContentView>
Sharada建议的链接中描述的方法对我不起作用。它的设计目的是确保在重叠视图的情况下,"较低"的视图有时会被点击。我需要相反的结果:我的点击需要转到顶部视图,但它会被包含的ContentView
捕获并处理。重新定义HitTest()
在这里没有帮助。
但尝试这种方法促使我使用自定义渲染器,最终我解决了这个问题。我只是定义了一个"原生"iOS手势识别器,而不是Xamarin.Forms
。如果我更熟悉原生iOS开发,我可能会更早地完成这项工作。我更喜欢安卓系统。
这是自定义渲染器代码。viewWithPoint.Frame.Size.Equals(Frame.Size)
是我如何在较小的子视图中确定点击是而不是的。我使用VisualElementRenderer<ContentView>
而不是ViewRenderer
,因为后者不能正确处理BackgroundColor
。
using CoreGraphics;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(MobileCatalog.LmcContentView), typeof(MobileCatalog.iOS.LmcContentViewRenderer))]
namespace MobileCatalog.iOS
{
/** Custom renderer in iOS is needed for the Overlay Content View:
* otherwise the "overlay" tap recognizer block taps inside its content */
public class LmcContentViewRenderer : VisualElementRenderer<ContentView>
{
public LmcContentViewRenderer()
{
UITapGestureRecognizer recognizer = new UITapGestureRecognizer((g) =>
{
if (Element != null)
LmcApp.W.ThePage.Overlay_Tapped(Element, null);
});
recognizer.ShouldBegin = ((g) =>
{
CGPoint point = g.LocationInView(this);
UIView viewWithPoint = HitTest(point, null);
return viewWithPoint != null && viewWithPoint.Frame.Size.Equals(Frame.Size);
});
AddGestureRecognizer(recognizer);
}
}
}