summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Android/GestureManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.Android/GestureManager.cs')
-rw-r--r--Xamarin.Forms.Platform.Android/GestureManager.cs172
1 files changed, 172 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.Android/GestureManager.cs b/Xamarin.Forms.Platform.Android/GestureManager.cs
new file mode 100644
index 00000000..62d5db64
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/GestureManager.cs
@@ -0,0 +1,172 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using Android.Support.V4.View;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class GestureManager : IDisposable
+ {
+ IVisualElementRenderer _renderer;
+ readonly Lazy<GestureDetector> _tapAndPanDetector;
+ readonly Lazy<ScaleGestureDetector> _scaleDetector;
+
+ bool _disposed;
+ bool _inputTransparent;
+ bool _isEnabled;
+
+ VisualElement Element => _renderer?.Element;
+
+ View View => _renderer?.Element as View;
+
+ global::Android.Views.View Control => _renderer?.View;
+
+ public GestureManager(IVisualElementRenderer renderer)
+ {
+ _renderer = renderer;
+ _renderer.ElementChanged += OnElementChanged;
+
+ _tapAndPanDetector = new Lazy<GestureDetector>(InitializeTapAndPanDetector);
+ _scaleDetector = new Lazy<ScaleGestureDetector>(InitializeScaleDetector);
+ }
+
+ public bool OnTouchEvent(MotionEvent e)
+ {
+ if (Control == null)
+ {
+ return false;
+ }
+
+ if (!_isEnabled || _inputTransparent)
+ {
+ return false;
+ }
+
+ if (!DetectorsValid())
+ {
+ return false;
+ }
+
+ var eventConsumed = false;
+ if (ViewHasPinchGestures())
+ {
+ eventConsumed = _scaleDetector.Value.OnTouchEvent(e);
+ }
+
+ eventConsumed = _tapAndPanDetector.Value.OnTouchEvent(e) || eventConsumed;
+
+ return eventConsumed;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ bool DetectorsValid()
+ {
+ // Make sure we're not testing for gestures on old motion events after our
+ // detectors have already been disposed
+
+ if (_scaleDetector.IsValueCreated && _scaleDetector.Value.Handle == IntPtr.Zero)
+ {
+ return false;
+ }
+
+ if (_tapAndPanDetector.IsValueCreated && _tapAndPanDetector.Value.Handle == IntPtr.Zero)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ GestureDetector InitializeTapAndPanDetector()
+ {
+ var listener = new InnerGestureListener(new TapGestureHandler(() => View),
+ new PanGestureHandler(() => View, Control.Context.FromPixels));
+
+ return new GestureDetector(listener);
+ }
+
+ ScaleGestureDetector InitializeScaleDetector()
+ {
+ var listener = new InnerScaleListener(new PinchGestureHandler(() => View));
+ var detector = new ScaleGestureDetector(Control.Context, listener, Control.Handler);
+ ScaleGestureDetectorCompat.SetQuickScaleEnabled(detector, true);
+
+ return detector;
+ }
+
+ bool ViewHasPinchGestures()
+ {
+ return View != null && View.GestureRecognizers.OfType<PinchGestureRecognizer>().Any();
+ }
+
+ void OnElementChanged(object sender, VisualElementChangedEventArgs e)
+ {
+ if (e.OldElement != null)
+ {
+ e.OldElement.PropertyChanged -= OnElementPropertyChanged;
+ }
+
+ if (e.NewElement != null)
+ {
+ e.NewElement.PropertyChanged += OnElementPropertyChanged;
+ }
+
+ UpdateInputTransparent();
+ UpdateIsEnabled();
+ }
+
+ void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == VisualElement.InputTransparentProperty.PropertyName)
+ UpdateInputTransparent();
+ else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled();
+ }
+
+ protected void Dispose(bool disposing)
+ {
+ if (_disposed)
+ {
+ return;
+ }
+
+ _disposed = true;
+
+ if (disposing)
+ {
+ if (Element != null)
+ {
+ Element.PropertyChanged -= OnElementPropertyChanged;
+ }
+
+ _renderer = null;
+ }
+ }
+
+ void UpdateInputTransparent()
+ {
+ if (Element == null)
+ {
+ return;
+ }
+
+ _inputTransparent = Element.InputTransparent;
+ }
+
+ void UpdateIsEnabled()
+ {
+ if (Element == null)
+ {
+ return;
+ }
+
+ _isEnabled = Element.IsEnabled;
+ }
+ }
+} \ No newline at end of file