Track tap gestures
This commit is contained in:
parent
0b60b4c800
commit
88a4798acb
|
@ -0,0 +1,169 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using Xamarin.Forms;
|
||||
|
||||
using NativeView = Ooui.Element;
|
||||
|
||||
namespace Ooui.Forms
|
||||
{
|
||||
public class EventTracker
|
||||
{
|
||||
readonly NotifyCollectionChangedEventHandler _collectionChangedHandler;
|
||||
|
||||
readonly Dictionary<IGestureRecognizer, NativeGestureRecognizer> _gestureRecognizers = new Dictionary<IGestureRecognizer, NativeGestureRecognizer> ();
|
||||
|
||||
readonly IVisualElementRenderer _renderer;
|
||||
bool _disposed;
|
||||
NativeView _handler;
|
||||
|
||||
public EventTracker (IVisualElementRenderer renderer)
|
||||
{
|
||||
if (renderer == null)
|
||||
throw new ArgumentNullException (nameof (renderer));
|
||||
|
||||
_collectionChangedHandler = ModelGestureRecognizersOnCollectionChanged;
|
||||
|
||||
_renderer = renderer;
|
||||
_renderer.ElementChanged += OnElementChanged;
|
||||
}
|
||||
|
||||
ObservableCollection<IGestureRecognizer> ElementGestureRecognizers {
|
||||
get {
|
||||
if (_renderer?.Element is View)
|
||||
return ((View)_renderer.Element).GestureRecognizers as ObservableCollection<IGestureRecognizer>;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
_disposed = true;
|
||||
|
||||
foreach (var kvp in _gestureRecognizers) {
|
||||
RemoveGestureRecognizer (_handler, kvp.Value);
|
||||
kvp.Value.Dispose ();
|
||||
}
|
||||
|
||||
_gestureRecognizers.Clear ();
|
||||
|
||||
if (ElementGestureRecognizers != null)
|
||||
ElementGestureRecognizers.CollectionChanged -= _collectionChangedHandler;
|
||||
|
||||
_handler = null;
|
||||
}
|
||||
|
||||
void ModelGestureRecognizersOnCollectionChanged (object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
|
||||
{
|
||||
LoadRecognizers ();
|
||||
}
|
||||
|
||||
void OnElementChanged (object sender, VisualElementChangedEventArgs e)
|
||||
{
|
||||
if (e.OldElement != null) {
|
||||
// unhook
|
||||
var oldView = e.OldElement as View;
|
||||
if (oldView != null) {
|
||||
var oldRecognizers = (ObservableCollection<IGestureRecognizer>)oldView.GestureRecognizers;
|
||||
oldRecognizers.CollectionChanged -= _collectionChangedHandler;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.NewElement != null) {
|
||||
// hook
|
||||
if (ElementGestureRecognizers != null) {
|
||||
ElementGestureRecognizers.CollectionChanged += _collectionChangedHandler;
|
||||
LoadRecognizers ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoadRecognizers ()
|
||||
{
|
||||
if (ElementGestureRecognizers == null)
|
||||
return;
|
||||
|
||||
foreach (var recognizer in ElementGestureRecognizers) {
|
||||
if (_gestureRecognizers.ContainsKey (recognizer))
|
||||
continue;
|
||||
|
||||
var nativeRecognizer = GetNativeRecognizer (recognizer);
|
||||
if (nativeRecognizer != null) {
|
||||
AddGestureRecognizer (_handler, nativeRecognizer);
|
||||
|
||||
_gestureRecognizers[recognizer] = nativeRecognizer;
|
||||
}
|
||||
}
|
||||
|
||||
var toRemove = _gestureRecognizers.Keys.Where (key => !ElementGestureRecognizers.Contains (key)).ToArray ();
|
||||
foreach (var gestureRecognizer in toRemove) {
|
||||
var uiRecognizer = _gestureRecognizers[gestureRecognizer];
|
||||
_gestureRecognizers.Remove (gestureRecognizer);
|
||||
|
||||
RemoveGestureRecognizer (_handler, uiRecognizer);
|
||||
uiRecognizer.Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual NativeGestureRecognizer GetNativeRecognizer (IGestureRecognizer recognizer)
|
||||
{
|
||||
if (recognizer == null)
|
||||
return null;
|
||||
|
||||
var weakRecognizer = new WeakReference (recognizer);
|
||||
var weakEventTracker = new WeakReference (this);
|
||||
|
||||
var tapRecognizer = recognizer as TapGestureRecognizer;
|
||||
if (tapRecognizer != null) {
|
||||
var returnAction = new TargetEventHandler ((s, e) => {
|
||||
var tapGestureRecognizer = weakRecognizer.Target as TapGestureRecognizer;
|
||||
var eventTracker = weakEventTracker.Target as EventTracker;
|
||||
var view = eventTracker?._renderer?.Element as View;
|
||||
|
||||
if (tapGestureRecognizer != null && view != null)
|
||||
tapGestureRecognizer.SendTapped (view);
|
||||
});
|
||||
var uiRecognizer = new NativeGestureRecognizer {
|
||||
EventType = "click",
|
||||
Handler = returnAction,
|
||||
};
|
||||
return uiRecognizer;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static void AddGestureRecognizer (Element element, NativeGestureRecognizer recognizer)
|
||||
{
|
||||
element.AddEventListener (recognizer.EventType, recognizer.Handler);
|
||||
}
|
||||
|
||||
static void RemoveGestureRecognizer (Element element, NativeGestureRecognizer recognizer)
|
||||
{
|
||||
element.RemoveEventListener (recognizer.EventType, recognizer.Handler);
|
||||
}
|
||||
|
||||
public void LoadEvents (NativeView handler)
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException (null);
|
||||
|
||||
_handler = handler;
|
||||
OnElementChanged (this, new VisualElementChangedEventArgs (null, _renderer.Element));
|
||||
}
|
||||
|
||||
protected class NativeGestureRecognizer : IDisposable
|
||||
{
|
||||
public string EventType;
|
||||
public TargetEventHandler Handler;
|
||||
public void Dispose ()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -57,6 +57,10 @@ namespace Ooui.Forms
|
|||
MessagingCenter.Unsubscribe<Page, ActionSheetArguments> (this, Page.ActionSheetSignalName);
|
||||
MessagingCenter.Unsubscribe<Page, AlertArguments> (this, Page.AlertSignalName);
|
||||
MessagingCenter.Unsubscribe<Page, bool> (this, Page.BusySetSignalName);
|
||||
|
||||
DisposeModelAndChildrenRenderers (Page);
|
||||
//foreach (var modal in _modals)
|
||||
//DisposeModelAndChildrenRenderers (modal);
|
||||
}
|
||||
|
||||
public static IVisualElementRenderer CreateRenderer (VisualElement element)
|
||||
|
@ -110,7 +114,29 @@ namespace Ooui.Forms
|
|||
|
||||
void HandleChildRemoved (object sender, ElementEventArgs e)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
var view = e.Element;
|
||||
DisposeModelAndChildrenRenderers (view);
|
||||
}
|
||||
|
||||
void DisposeModelAndChildrenRenderers (Xamarin.Forms.Element view)
|
||||
{
|
||||
IVisualElementRenderer renderer;
|
||||
foreach (VisualElement child in view.Descendants ()) {
|
||||
renderer = GetRenderer (child);
|
||||
child.ClearValue (RendererProperty);
|
||||
|
||||
if (renderer != null) {
|
||||
//renderer.NativeView.RemoveFromSuperview ();
|
||||
renderer.Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
renderer = GetRenderer ((VisualElement)view);
|
||||
if (renderer != null) {
|
||||
//renderer.NativeView.RemoveFromSuperview ();
|
||||
renderer.Dispose ();
|
||||
}
|
||||
view.ClearValue (RendererProperty);
|
||||
}
|
||||
|
||||
void AddChild (VisualElement view)
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace Ooui.Forms
|
|||
|
||||
VisualElementRendererFlags _flags = VisualElementRendererFlags.AutoPackage | VisualElementRendererFlags.AutoTrack;
|
||||
|
||||
EventTracker _events;
|
||||
VisualElementPackager _packager;
|
||||
VisualElementTracker _tracker;
|
||||
|
||||
|
@ -107,10 +108,10 @@ namespace Ooui.Forms
|
|||
_packager.Load ();
|
||||
}
|
||||
|
||||
//if (AutoTrack && _events == null) {
|
||||
// _events = new EventTracker (this);
|
||||
// _events.LoadEvents (this);
|
||||
//}
|
||||
if (AutoTrack && _events == null) {
|
||||
_events = new EventTracker (this);
|
||||
_events.LoadEvents (this);
|
||||
}
|
||||
|
||||
element.PropertyChanged += _propertyChangedHandler;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue