Xamarin形式處理當前的唯一手勢是Tap和DoubleTap默認這些泡沫。對於Android來說,Windows和大概IOS都會以不同的方式處理其他手勢。
快速回顧事件的Xamarin.Forms世界處理的:
在Android 手勢被渲染的每個渲染器的觸摸事件進行處理。當手勢發生時,觸摸在渲染器中引發。通過訂閱Touch事件並添加EventArgs,您可以確定屏幕上發生了什麼。現在,您可以自己做出關於用戶正在做什麼的所有決定,或者使用Mono.Android.GestureDetector爲您做出這些決定。 GestureDetector需要一個GestureListener,它在它認爲發生了像tap或double這樣的事件時通知它。然後你的手勢監聽器可以包含你想要響應這些事件的任何代碼。
在Windows 每個本地控制決定爲自己當發生一個事件,並公開了一組事件處理這些事件。要響應這些事件,您需要創建一個自定義渲染器並訂閱本機控件上的事件,然後執行您自己的代碼。
關於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"
}
}
};
}
}
讓我們把一些自定義渲染在一起,看看發生了什麼。首先,我們需要一個渲染器來處理堆棧中的每個控件,所以在我們的例子中是一個標籤渲染器和一個幀渲染器。
我們將在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;
在我們的標籤渲染起泡和框架絕不會通知按住事件。
現在For 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;
}
}
}
如果我們運行這個看起來一切正常一樣的窗戶,我們木屐在標籤觸摸事件,並在框架中的觸摸事件。冒泡似乎是自動的。當我們嘗試禁用冒泡時它變得雜亂。如果我們改變
e.Handled = true;
在標籤渲染器中,並再次運行該應用程序--- 在LABEL RENDERER中觸摸兩次。一次當我們觸摸屏幕時,一次當我們停下來時。如果我們設置labelrenderer的e.Handled = false;並將Frame設置爲true。然後,標籤觸發隨後的框架,但只有框架第二次觸發。
另外,如果我們從渲染器中刪除e.Handled = false並運行應用程序,我們會發現只有LabelRenderer的Touch事件觸發。暗示Handled的默認值是正確的。如果您在渲染器中未設置e.Handled = false,則該事件將在LabelRenderer中觸發,而不會將堆棧向上渲染到FrameRenderer。
結論: Bubbling在Windows上開箱即用。在Android上,它不會像你所期望的那樣工作。首先,你必須在每個孩子中明確地設置Handled = false,這樣父母才能得到通知,即使只有處理事件的Handler得到通知,觸摸事件結束了堆棧的其餘部分纔會得到啓動的通知,但從來不知道它的結束。
哪個平臺? – Cheesebaron
@Cheesebaron Xamarin.Forms。現在增加它的問題。謝謝 – Dbl