我目前正在为Xamarin.Forms开发SideDrawer,因为在这一点上,来自telerik的那个是相当糟糕的副作用。
我知道如何在WPF中执行此操作,因为它非常简单,但在Xamarin中却有所不同。
我的GestureFrame代码与this几乎相同。
我已使用some github project / xamarin docs / XLabs上的来源开始使用。起初它进展顺利,但是一旦我将控件置于手势框内,我将不再接收任何事件,因为子控件似乎消耗了任何触摸/手势事件。
这对任何人都响了吗?现在我不确定我可能做错了控制行为这样
答案 0 :(得分:1)
Xamarin Forms目前处理的唯一手势是Tap和DoubleTap默认情况下这些冒泡。对于Android,Windows和大概IOS每个处理其他手势的方式不同。
Xamarin.Forms世界中事件处理的快速回顾:
在Android上 手势由渲染器处理,每个渲染器都有一个Touch事件。发生手势时,在渲染器中触摸。通过订阅Touch事件并更新EventArgs,您可以确定屏幕上发生了什么。现在,您可以自己决定用户正在做什么,或者使用Mono.Android.GestureDetector为您做出决定。 GestureDetector需要一个GestureListener,当它认为发生了tap或double这样的事件时会通知它。然后,您的Gesture监听器可以包含您想要响应这些事件的任何代码。
在Windows上 每个本机控件在事件发生时自行确定并为这些事件公开一组EventHandler。要响应这些事件,您需要创建一个自定义渲染器并订阅本机控件上的事件,然后执行您自己的代码。
在IOS上? 不知道在我的项目中还没有那么远https://github.com/Indiponics/IndiXam-Lib也许其他人可以给你那件作品。
冒泡活动 让我们看一个简单的冒泡情况:
public class App : Application
{
public App()
{
// The root page of your application
MainPage = new ContentPage
{
Content = new Frame
{
Content =
new Label {
Text = "Hold Me, Thrill Me, Kiss Me"
}
}
};
}
}
让我们把一些自定义渲染器放在一起,看看发生了什么。首先,我们需要为堆栈中的每个控件提供渲染器,因此在我们的示例中为Label Renderer和Frame Renderer。
我们将从Windows开始:
[assembly: ExportRenderer(typeof(Label), typeof(myLabelCustomRenderer))]
[assembly: ExportRenderer(typeof(Frame), typeof(myFrameCustomRenderer))]
namespace App4.WinPhone
{
public class myFrameCustomRenderer:FrameRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Frame> e)
{
base.OnElementChanged(e);
if(e.NewElement!=null)
{
this.Control.Hold += Control_Hold;
}
}
void Control_Hold(object sender, System.Windows.Input.GestureEventArgs e)
{
System.Diagnostics.Debug.WriteLine("Frame Held");
e.Handled = false;
}
}
public class myLabelCustomRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Label> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
this.Control.Hold += Control_Hold;
}
}
void Control_Hold(object sender, System.Windows.Input.GestureEventArgs e)
{
System.Diagnostics.Debug.WriteLine("Label Held");
e.Handled = false;
}
}
}
运行这个,我们发现了 在Windows中默认冒泡。如果我们想要通过改变
来关闭冒泡e.Handled = true;
在我们的标签渲染器中,框架永远不会收到保持事件的通知。
现在适用于Android 在Android上,事情变得有点麻烦。我们将再次创建两个渲染器。
[assembly: ExportRenderer(typeof(Label), typeof(myLabelCustomRenderer))]
[assembly: ExportRenderer(typeof(Frame), typeof(myFrameCustomRenderer))]
namespace App4.Droid
{
public class myFrameCustomRenderer : FrameRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Frame> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
this.Touch += myFrameCustomRenderer_Touch;
}
}
void myFrameCustomRenderer_Touch(object sender, Android.Views.View.TouchEventArgs e)
{
System.Diagnostics.Debug.WriteLine("You Touched My Frame");
e.Handled = false;
}
}
public class myLabelCustomRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Label> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
this.Touch += myFrameCustomRenderer_Touch;
}
}
void myFrameCustomRenderer_Touch(object sender, Android.Views.View.TouchEventArgs e)
{
System.Diagnostics.Debug.WriteLine("You Touched My Label");
e.Handled = false;
}
}
}
如果我们运行它,看起来一切都与windows我们geta触摸标签中的事件和框架中的触摸事件相同。冒泡似乎是自动的。当我们尝试禁用冒泡时,它会变得混乱。如果我们改变
e.Handled = TRUE;
在标签渲染器中再次运行应用程序--- 在标签RENDERER中触摸两次。一旦我们触摸屏幕,一旦我们停止。如果我们设置labelrenderer的e.Handled = false;并将Frame设置为true。然后标签触摸后跟帧,但只有帧触发第二次。
此外,如果我们从两个渲染器中删除e.Handled = false并运行应用程序,我们发现只有LabelRenderer的Touch事件会触发。暗示Handled的默认值似乎为真。如果未在渲染器中设置e.Handled = false,则事件将在LabelRenderer中触发,而不会将堆栈冒泡到FrameRenderer。
结论: 冒泡在Windows上开箱即用。在Android上它不会像你期望的那样工作。首先,您必须在每个子节点中显式设置Handled = false,以便父节点获得通知,然后只有处理事件的处理程序才会收到通知,触摸事件结束,其余的堆栈会收到启动通知,但从不知道它的结束