问题描述
这是我的XAML.该ContentView
位于AbsoluteLayout
内部,但我认为这并不重要.这个想法是要有一个带有列表视图的框架,并在其周围有一个深色的背景.如果用户在Frame
之外单击,我希望收到Overlay_Tapped
.
Here is my XAML. This ContentView
is inside an AbsoluteLayout
, but I don't think that matters. The idea is to have a frame with a list view, and a darkened background around it. I want to receive Overlay_Tapped
if the user clicks outside of the Frame
.
在iOS中,从不调用SpinnerList_ItemSelected
.相反,即使用户单击Frame
的内部 ,Overlay_Tapped
也是.在Android中一切正常.
In iOS, SpinnerList_ItemSelected
is never called. Instead, Overlay_Tapped
is, even if the user clicks inside the Frame
. In Android everything is fine.
我尝试在Frame
,ListView
甚至ViewCell
中设置InputTransparent="False"
.无济于事.有用的是在TapGestureRecognizer
中设置NumberOfTapsRequired="2"
,但这显然不是我的意图.
I tried setting InputTransparent="False"
in the Frame
, ListView
, and even the ViewCell
. Does not help. What helps is setting NumberOfTapsRequired="2"
in the TapGestureRecognizer
, but that's obviously not my intention.
帮助?
<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>
推荐答案
The approach described in the link suggested by Sharada does not work for me. It was designed to make sure that in case of overlaying views, the "lower" one sometimes gets the tap. I need the opposite: my tap needs to go to the top view, but it gets caught and processed by the containing ContentView
. Redefining HitTest()
does not help here.
但是尝试这种方法将我推入了自定义渲染器中,并且最终我能够解决我的问题.我只是定义了一个本地" iOS手势识别器,而不是Xamarin.Forms
.如果我更熟悉本机iOS开发,我可能会更早完成.我更像是一个Android人.
But trying this approach pushed me into custom renderers, and I was eventually able to solve my issue. I simply defined a "native" iOS gesture recognizer instead of a Xamarin.Forms
one. I would've probably done this earlier if I was more familiar with native iOS development. I'm more of an Android guy.
这是自定义渲染器代码. viewWithPoint.Frame.Size.Equals(Frame.Size)
是我确定在较小的子视图中单击是 not 的方式.我使用的是VisualElementRenderer<ContentView>
而不是ViewRenderer
,因为后者不能正确处理BackgroundColor
.
Here is the custom renderer code. viewWithPoint.Frame.Size.Equals(Frame.Size)
is how I determine that the click was not in a smaller subview. I'm using VisualElementRenderer<ContentView>
instead of ViewRenderer
as the latter does not properly process 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);
}
}
}
这篇关于iOS中的InputTransparent的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!