summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Android
diff options
context:
space:
mode:
authorE.Z. Hart <hartez@users.noreply.github.com>2017-09-15 18:49:19 (GMT)
committerRui Marinho <me@ruimarinho.net>2017-09-15 19:28:38 (GMT)
commitfc3ad54edbe4f7e33e2d8c4f9bc217b93dd62ecc (patch)
treee63d0d922f62198993735c34811ede1a0d69f1b8 /Xamarin.Forms.Platform.Android
parentd1bf93be200b3d3c48d0d292bf455f444485d8f9 (diff)
downloadxamarin-forms-fc3ad54edbe4f7e33e2d8c4f9bc217b93dd62ecc.zip
xamarin-forms-fc3ad54edbe4f7e33e2d8c4f9bc217b93dd62ecc.tar.gz
xamarin-forms-fc3ad54edbe4f7e33e2d8c4f9bc217b93dd62ecc.tar.bz2
[Android] Restore pinch gestures and fix listview item selection (#1135)
* Repro * Fail test if tap command is executed more than once. * Update error message * Handle context actions and taps without breaking selection * Fix 58833 test * Prevent InnerGestureListener from swallowing clicks and preventing selection * Repro for 57515 * Add gestures category to appropriate tests * Test notes * Restore the tap gesture handling * Better test name * Simplify InnerGestureListener constructor; handle OnDown only if listening * OnInterceptTouchEvent for IsEnabled handling * Fix incorrect class filter in TapGestureHandler * Restore MotionEventHelper * Add IsEnabled check on OnTouchEvent * Reinstate pinch gestures * Checkpoint (trying to figure out how to handle button elevation) * Rip out elevation ordering in DefaultRenderer * Working version of pinch-to-zoom test * Clean up lazy initializers, remove unnecessary members * One fewer Java.Lang.Object * Fix issue number; clean up notes and issue number changes * Remove conditional * Restore correct issue number * Automate all the options for 58833 test * Remove unnecessary automation ID * Formatting cleanup; reinstate gesture detector dispose checks * Updating Xamarin UI test version to avoid iOS crashes; update test to open iOS context actions * Attempting to get 58833 test running on all iOS versions
Diffstat (limited to 'Xamarin.Forms.Platform.Android')
-rw-r--r--Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs120
-rw-r--r--Xamarin.Forms.Platform.Android/FastRenderers/FrameRenderer.cs10
-rw-r--r--Xamarin.Forms.Platform.Android/FastRenderers/GestureManager.cs267
-rw-r--r--Xamarin.Forms.Platform.Android/FastRenderers/ImageRenderer.cs15
-rw-r--r--Xamarin.Forms.Platform.Android/FastRenderers/LabelRenderer.cs12
-rw-r--r--Xamarin.Forms.Platform.Android/FastRenderers/VisualElementRenderer.cs4
-rw-r--r--Xamarin.Forms.Platform.Android/GestureManager.cs172
-rw-r--r--Xamarin.Forms.Platform.Android/InnerGestureListener.cs98
-rw-r--r--Xamarin.Forms.Platform.Android/InnerScaleListener.cs20
-rw-r--r--Xamarin.Forms.Platform.Android/PanGestureHandler.cs7
-rw-r--r--Xamarin.Forms.Platform.Android/PinchGestureHandler.cs18
-rw-r--r--Xamarin.Forms.Platform.Android/Platform.cs30
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs16
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs15
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ViewCellExtensions.cs19
-rw-r--r--Xamarin.Forms.Platform.Android/TapGestureHandler.cs6
-rw-r--r--Xamarin.Forms.Platform.Android/VisualElementExtensions.cs14
-rw-r--r--Xamarin.Forms.Platform.Android/VisualElementPackager.cs1
-rw-r--r--Xamarin.Forms.Platform.Android/VisualElementRenderer.cs180
-rw-r--r--Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj2
20 files changed, 457 insertions, 569 deletions
diff --git a/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs
index 7524622..44f2bbb 100644
--- a/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs
@@ -3,6 +3,8 @@ using Android.Views;
using AView = Android.Views.View;
using Xamarin.Forms.Internals;
using System;
+using System.Linq;
+using Android.Runtime;
namespace Xamarin.Forms.Platform.Android
{
@@ -53,8 +55,48 @@ namespace Xamarin.Forms.Platform.Android
readonly BindableProperty _unevenRows;
IVisualElementRenderer _view;
ViewCell _viewCell;
+ GestureDetector _longPressGestureDetector;
+ ListViewRenderer _listViewRenderer;
+ bool _watchForLongPress;
- public ViewCellContainer(Context context, IVisualElementRenderer view, ViewCell viewCell, View parent, BindableProperty unevenRows, BindableProperty rowHeight) : base(context)
+ ListViewRenderer ListViewRenderer
+ {
+ get
+ {
+ if (_listViewRenderer != null)
+ {
+ return _listViewRenderer;
+ }
+
+ var listView = _parent as ListView;
+
+ if (listView == null)
+ {
+ return null;
+ }
+
+ _listViewRenderer = Platform.GetRenderer(listView) as ListViewRenderer;
+
+ return _listViewRenderer;
+ }
+ }
+
+ GestureDetector LongPressGestureDetector
+ {
+ get
+ {
+ if (_longPressGestureDetector != null)
+ {
+ return _longPressGestureDetector;
+ }
+
+ _longPressGestureDetector = new GestureDetector(new LongPressGestureListener(TriggerLongClick));
+ return _longPressGestureDetector;
+ }
+ }
+
+ public ViewCellContainer(Context context, IVisualElementRenderer view, ViewCell viewCell, View parent,
+ BindableProperty unevenRows, BindableProperty rowHeight) : base(context)
{
_view = view;
_parent = parent;
@@ -63,7 +105,7 @@ namespace Xamarin.Forms.Platform.Android
_viewCell = viewCell;
AddView(view.View);
UpdateIsEnabled();
- UpdateLongClickable();
+ UpdateWatchForLongPress();
}
protected bool ParentHasUnevenRows
@@ -86,6 +128,11 @@ namespace Xamarin.Forms.Platform.Android
if (!Enabled)
return true;
+ if (_watchForLongPress)
+ {
+ LongPressGestureDetector.OnTouchEvent(ev);
+ }
+
return base.OnInterceptTouchEvent(ev);
}
@@ -137,7 +184,7 @@ namespace Xamarin.Forms.Platform.Android
AddView(_view.View);
UpdateIsEnabled();
- UpdateLongClickable();
+ UpdateWatchForLongPress();
Performance.Stop();
}
@@ -182,12 +229,69 @@ namespace Xamarin.Forms.Platform.Android
Performance.Stop();
}
- void UpdateLongClickable()
+ void UpdateWatchForLongPress()
{
- // In order for context menu long presses/clicks to work on ViewCells which have
- // and Clickable content, we have to make the container view LongClickable
- // If we don't have a context menu, we don't have to worry about it
- _view.View.LongClickable = _viewCell.ContextActions.Count > 0;
+ var vw = _view.Element as Xamarin.Forms.View;
+ if (vw == null)
+ {
+ return;
+ }
+
+ // If the view cell has any context actions and the View itself has any Tap Gestures, they're going
+ // to conflict with one another - the Tap Gesture handling will prevent the ListViewAdapter's
+ // LongClick handling from happening. So we need to watch locally for LongPress and if we see it,
+ // trigger the LongClick manually.
+ _watchForLongPress = _viewCell.ContextActions.Count > 0
+ && vw.GestureRecognizers.Any(t => t is TapGestureRecognizer);
+ }
+
+ void TriggerLongClick()
+ {
+ ListViewRenderer?.LongClickOn(this);
+ }
+
+ internal class LongPressGestureListener : Java.Lang.Object, GestureDetector.IOnGestureListener
+ {
+ readonly Action _onLongClick;
+
+ internal LongPressGestureListener(Action onLongClick)
+ {
+ _onLongClick = onLongClick;
+ }
+
+ internal LongPressGestureListener(IntPtr handle, JniHandleOwnership ownership) : base(handle, ownership)
+ {
+ }
+
+ public bool OnDown(MotionEvent e)
+ {
+ return true;
+ }
+
+ public bool OnFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
+ {
+ return false;
+ }
+
+ public void OnLongPress(MotionEvent e)
+ {
+ _onLongClick();
+ }
+
+ public bool OnScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
+ {
+ return false;
+ }
+
+ public void OnShowPress(MotionEvent e)
+ {
+
+ }
+
+ public bool OnSingleTapUp(MotionEvent e)
+ {
+ return false;
+ }
}
}
}
diff --git a/Xamarin.Forms.Platform.Android/FastRenderers/FrameRenderer.cs b/Xamarin.Forms.Platform.Android/FastRenderers/FrameRenderer.cs
index 3239715..0adaf85 100644
--- a/Xamarin.Forms.Platform.Android/FastRenderers/FrameRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/FastRenderers/FrameRenderer.cs
@@ -23,6 +23,7 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
readonly GestureManager _gestureManager;
readonly EffectControlProvider _effectControlProvider;
+ readonly MotionEventHelper _motionEventHelper = new MotionEventHelper();
public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
public event EventHandler<PropertyChangedEventArgs> ElementPropertyChanged;
@@ -68,6 +69,7 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
if (frame == null)
throw new ArgumentException("Element must be of type Frame");
Element = frame;
+ _motionEventHelper.UpdateElement(frame);
if (!string.IsNullOrEmpty(Element.AutomationId))
ContentDescription = Element.AutomationId;
@@ -182,10 +184,12 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
public override bool OnTouchEvent(MotionEvent e)
{
- bool handled;
- var result = _gestureManager.OnTouchEvent(e, Parent, out handled);
+ if (_gestureManager.OnTouchEvent(e))
+ {
+ return true;
+ }
- return handled ? result : base.OnTouchEvent(e);
+ return _motionEventHelper.HandleMotionEvent(Parent, e);
}
protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
diff --git a/Xamarin.Forms.Platform.Android/FastRenderers/GestureManager.cs b/Xamarin.Forms.Platform.Android/FastRenderers/GestureManager.cs
deleted file mode 100644
index ec10138..0000000
--- a/Xamarin.Forms.Platform.Android/FastRenderers/GestureManager.cs
+++ /dev/null
@@ -1,267 +0,0 @@
-using System;
-using System.Collections.ObjectModel;
-using System.Collections.Specialized;
-using System.ComponentModel;
-using Android.Support.V4.View;
-using Android.Views;
-using Object = Java.Lang.Object;
-
-namespace Xamarin.Forms.Platform.Android.FastRenderers
-{
- internal class GestureManager : Object, global::Android.Views.View.IOnClickListener, global::Android.Views.View.IOnTouchListener
- {
- IVisualElementRenderer _renderer;
- readonly Lazy<GestureDetector> _gestureDetector;
- readonly PanGestureHandler _panGestureHandler;
- readonly PinchGestureHandler _pinchGestureHandler;
- readonly Lazy<ScaleGestureDetector> _scaleDetector;
- readonly TapGestureHandler _tapGestureHandler;
- readonly MotionEventHelper _motionEventHelper = new MotionEventHelper();
- InnerGestureListener _gestureListener;
-
- bool _clickable;
- bool _disposed;
- bool _inputTransparent;
- bool _isEnabled;
-
- NotifyCollectionChangedEventHandler _collectionChangeHandler;
-
- 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;
-
- _tapGestureHandler = new TapGestureHandler(() => View);
- _panGestureHandler = new PanGestureHandler(() => View, Control.Context.FromPixels);
- _pinchGestureHandler = new PinchGestureHandler(() => View);
- _gestureDetector =
- new Lazy<GestureDetector>(
- () =>
- new GestureDetector(
- _gestureListener =
- new InnerGestureListener(_tapGestureHandler.OnTap, _tapGestureHandler.TapGestureRecognizers,
- _panGestureHandler.OnPan, _panGestureHandler.OnPanStarted, _panGestureHandler.OnPanComplete)));
-
- _scaleDetector =
- new Lazy<ScaleGestureDetector>(
- () =>
- new ScaleGestureDetector(Control.Context,
- new InnerScaleListener(_pinchGestureHandler.OnPinch, _pinchGestureHandler.OnPinchStarted,
- _pinchGestureHandler.OnPinchEnded), Control.Handler));
-
- Control.SetOnClickListener(this);
- Control.SetOnTouchListener(this);
- }
-
- public bool OnTouchEvent(MotionEvent e, IViewParent parent, out bool handled)
- {
- if (_inputTransparent)
- {
- handled = true;
- return false;
- }
-
- if (View.GestureRecognizers.Count == 0)
- {
- handled = true;
- return _motionEventHelper.HandleMotionEvent(parent, e);
- }
-
- handled = false;
- return false;
- }
-
- void OnElementChanged(object sender, VisualElementChangedEventArgs e)
- {
- if (e.OldElement != null)
- {
- UnsubscribeGestureRecognizers(e.OldElement);
- e.OldElement.PropertyChanged -= OnElementPropertyChanged;
- }
-
- if (e.NewElement != null)
- {
- UpdateGestureRecognizers(true);
- SubscribeGestureRecognizers(e.NewElement);
- _motionEventHelper.UpdateElement(e.NewElement);
- 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 override void Dispose(bool disposing)
- {
- if (_disposed)
- {
- return;
- }
-
- _disposed = true;
-
- if (disposing)
- {
- if (Element != null)
- {
- Element.PropertyChanged -= OnElementPropertyChanged;
- }
-
- Control.SetOnClickListener(null);
- Control.SetOnTouchListener(null);
-
- if (_gestureListener != null)
- {
- _gestureListener.Dispose();
- _gestureListener = null;
- }
-
- if (_renderer?.Element != null)
- {
- UnsubscribeGestureRecognizers(Element);
- }
-
- _renderer = null;
- }
-
- base.Dispose(disposing);
- }
-
- void global::Android.Views.View.IOnClickListener.OnClick(global::Android.Views.View v)
- {
- _tapGestureHandler.OnSingleClick();
- }
-
- bool global::Android.Views.View.IOnTouchListener.OnTouch(global::Android.Views.View v, MotionEvent e)
- {
- if (!_isEnabled)
- return true;
-
- if (_inputTransparent)
- return false;
-
- var handled = false;
- if (_pinchGestureHandler.IsPinchSupported)
- {
- if (!_scaleDetector.IsValueCreated)
- ScaleGestureDetectorCompat.SetQuickScaleEnabled(_scaleDetector.Value, true);
- handled = _scaleDetector.Value.OnTouchEvent(e);
- }
-
- if (_gestureDetector.IsValueCreated && _gestureDetector.Value.Handle == IntPtr.Zero)
- {
- // This gesture detector has already been disposed, probably because it's on a cell which is going away
- return handled;
- }
-
- // It's very important that the gesture detection happen first here
- // if we check handled first, we might short-circuit and never check for tap/pan
- handled = _gestureDetector.Value.OnTouchEvent(e) || handled;
-
- v.EnsureLongClickCancellation(e, handled, Element);
-
- return handled;
- }
-
- void HandleGestureRecognizerCollectionChanged(object sender,
- NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
- {
- UpdateGestureRecognizers();
- }
-
- void SubscribeGestureRecognizers(VisualElement element)
- {
- var view = element as View;
- if (view == null)
- {
- return;
- }
-
- if (_collectionChangeHandler == null)
- {
- _collectionChangeHandler = HandleGestureRecognizerCollectionChanged;
- }
-
- var observableCollection = (ObservableCollection<IGestureRecognizer>)view.GestureRecognizers;
- if (observableCollection != null)
- {
- observableCollection.CollectionChanged += _collectionChangeHandler;
- }
- }
-
- void UnsubscribeGestureRecognizers(VisualElement element)
- {
- var view = element as View;
- if (view == null || _collectionChangeHandler == null)
- {
- return;
- }
-
- var observableCollection = (ObservableCollection<IGestureRecognizer>)view.GestureRecognizers;
- if (observableCollection != null)
- {
- observableCollection.CollectionChanged -= _collectionChangeHandler;
- }
- }
-
- void UpdateClickable(bool force = false)
- {
- var view = Element as View;
- if (view == null)
- {
- return;
- }
-
- bool newValue = view.ShouldBeMadeClickable();
- if (force || _clickable != newValue)
- {
- Control.Clickable = newValue;
- _clickable = newValue;
- }
- }
-
- void UpdateGestureRecognizers(bool forceClick = false)
- {
- if (Element == null)
- {
- return;
- }
-
- UpdateClickable(forceClick);
- }
-
- void UpdateInputTransparent()
- {
- if (Element == null)
- {
- return;
- }
-
- _inputTransparent = Element.InputTransparent;
- }
-
- void UpdateIsEnabled()
- {
- if (Element == null)
- {
- return;
- }
-
- _isEnabled = Element.IsEnabled;
- }
- }
-} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/FastRenderers/ImageRenderer.cs b/Xamarin.Forms.Platform.Android/FastRenderers/ImageRenderer.cs
index 24623b2..6e15235 100644
--- a/Xamarin.Forms.Platform.Android/FastRenderers/ImageRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/FastRenderers/ImageRenderer.cs
@@ -16,6 +16,7 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
int? _defaultLabelFor;
VisualElementTracker _visualElementTracker;
VisualElementRenderer _visualElementRenderer;
+ readonly MotionEventHelper _motionEventHelper = new MotionEventHelper();
protected override void Dispose(bool disposing)
{
@@ -71,12 +72,14 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
}
public override bool OnTouchEvent(MotionEvent e)
- {
- bool handled;
- var result = _visualElementRenderer.OnTouchEvent(e, Parent, out handled);
+ {
+ if (_visualElementRenderer.OnTouchEvent(e))
+ {
+ return true;
+ }
- return handled ? result : base.OnTouchEvent(e);
- }
+ return _motionEventHelper.HandleMotionEvent(Parent, e);
+ }
Size MinimumSize()
{
@@ -122,7 +125,7 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
}
Internals.Performance.Stop();
-
+ _motionEventHelper.UpdateElement(element);
OnElementChanged(new ElementChangedEventArgs<Image>(oldElement, _element));
_element?.SendViewInitialized(Control);
diff --git a/Xamarin.Forms.Platform.Android/FastRenderers/LabelRenderer.cs b/Xamarin.Forms.Platform.Android/FastRenderers/LabelRenderer.cs
index f92873b..bcf8398 100644
--- a/Xamarin.Forms.Platform.Android/FastRenderers/LabelRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/FastRenderers/LabelRenderer.cs
@@ -23,7 +23,8 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
Color _lastUpdateColor = Color.Default;
VisualElementTracker _visualElementTracker;
VisualElementRenderer _visualElementRenderer;
-
+ readonly MotionEventHelper _motionEventHelper = new MotionEventHelper();
+
bool _wasFormatted;
public LabelRenderer() : base(Forms.Context)
@@ -112,6 +113,7 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
throw new ArgumentException("Element must be of type Label");
Element = label;
+ _motionEventHelper.UpdateElement(element);
}
void IVisualElementRenderer.SetLabelFor(int? id)
@@ -163,10 +165,12 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
public override bool OnTouchEvent(MotionEvent e)
{
- bool handled;
- var result = _visualElementRenderer.OnTouchEvent(e, Parent, out handled);
+ if (_visualElementRenderer.OnTouchEvent(e))
+ {
+ return true;
+ }
- return handled ? result : base.OnTouchEvent(e);
+ return _motionEventHelper.HandleMotionEvent(Parent, e);
}
void OnElementChanged(ElementChangedEventArgs<Label> e)
diff --git a/Xamarin.Forms.Platform.Android/FastRenderers/VisualElementRenderer.cs b/Xamarin.Forms.Platform.Android/FastRenderers/VisualElementRenderer.cs
index 91943fb..c696768 100644
--- a/Xamarin.Forms.Platform.Android/FastRenderers/VisualElementRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/FastRenderers/VisualElementRenderer.cs
@@ -45,9 +45,9 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
Control.SetBackgroundColor((color ?? Element.BackgroundColor).ToAndroid());
}
- public bool OnTouchEvent(MotionEvent e, IViewParent parent, out bool handled)
+ public bool OnTouchEvent(MotionEvent e)
{
- return _gestureManager.OnTouchEvent(e, parent, out handled);
+ return _gestureManager.OnTouchEvent(e);
}
public void Dispose()
diff --git a/Xamarin.Forms.Platform.Android/GestureManager.cs b/Xamarin.Forms.Platform.Android/GestureManager.cs
new file mode 100644
index 0000000..62d5db6
--- /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
diff --git a/Xamarin.Forms.Platform.Android/InnerGestureListener.cs b/Xamarin.Forms.Platform.Android/InnerGestureListener.cs
index 928c9c1..99c1d63 100644
--- a/Xamarin.Forms.Platform.Android/InnerGestureListener.cs
+++ b/Xamarin.Forms.Platform.Android/InnerGestureListener.cs
@@ -9,6 +9,8 @@ namespace Xamarin.Forms.Platform.Android
{
internal class InnerGestureListener : Object, GestureDetector.IOnGestureListener, GestureDetector.IOnDoubleTapListener
{
+ readonly TapGestureHandler _tapGestureHandler;
+ readonly PanGestureHandler _panGestureHandler;
bool _isScrolling;
float _lastX;
float _lastY;
@@ -20,25 +22,31 @@ namespace Xamarin.Forms.Platform.Android
Func<int, bool> _tapDelegate;
Func<int, IEnumerable<TapGestureRecognizer>> _tapGestureRecognizers;
- public InnerGestureListener(Func<int, bool> tapDelegate, Func<int, IEnumerable<TapGestureRecognizer>> tapGestureRecognizers, Func<float, float, int, bool> scrollDelegate,
- Func<int, bool> scrollStartedDelegate, Func<bool> scrollCompleteDelegate)
+ public InnerGestureListener(TapGestureHandler tapGestureHandler, PanGestureHandler panGestureHandler)
{
- if (tapDelegate == null)
- throw new ArgumentNullException(nameof(tapDelegate));
- if (tapGestureRecognizers == null)
- throw new ArgumentNullException(nameof(tapGestureRecognizers));
- if (scrollDelegate == null)
- throw new ArgumentNullException(nameof(scrollDelegate));
- if (scrollStartedDelegate == null)
- throw new ArgumentNullException(nameof(scrollStartedDelegate));
- if (scrollCompleteDelegate == null)
- throw new ArgumentNullException(nameof(scrollCompleteDelegate));
+ if (tapGestureHandler == null)
+ {
+ throw new ArgumentNullException(nameof(tapGestureHandler));
+ }
+
+ if (panGestureHandler == null)
+ {
+ throw new ArgumentNullException(nameof(panGestureHandler));
+ }
+
+ _tapGestureHandler = tapGestureHandler;
+ _panGestureHandler = panGestureHandler;
- _tapDelegate = tapDelegate;
- _tapGestureRecognizers = tapGestureRecognizers;
- _scrollDelegate = scrollDelegate;
- _scrollStartedDelegate = scrollStartedDelegate;
- _scrollCompleteDelegate = scrollCompleteDelegate;
+ _tapDelegate = tapGestureHandler.OnTap;
+ _tapGestureRecognizers = tapGestureHandler.TapGestureRecognizers;
+ _scrollDelegate = panGestureHandler.OnPan;
+ _scrollStartedDelegate = panGestureHandler.OnPanStarted;
+ _scrollCompleteDelegate = panGestureHandler.OnPanComplete;
+ }
+
+ bool HasAnyGestures()
+ {
+ return _panGestureHandler.HasAnyGestures() || _tapGestureHandler.HasAnyGestures();
}
// This is needed because GestureRecognizer callbacks can be delayed several hundred milliseconds
@@ -48,16 +56,6 @@ namespace Xamarin.Forms.Platform.Android
{
}
- internal void OnTouchEvent(MotionEvent e)
- {
- if (e.Action == MotionEventActions.Up)
- EndScrolling();
- else if (e.Action == MotionEventActions.Down)
- SetStartingPosition(e);
- else if (e.Action == MotionEventActions.Move)
- StartScrolling(e);
- }
-
bool GestureDetector.IOnDoubleTapListener.OnDoubleTap(MotionEvent e)
{
if (_disposed)
@@ -71,21 +69,19 @@ namespace Xamarin.Forms.Platform.Android
return false;
}
- bool GestureDetector.IOnDoubleTapListener.OnSingleTapConfirmed(MotionEvent e)
- {
- if (_disposed)
- return false;
-
- // optimization: only wait for a second tap if there is a double tap handler
- if (!HasDoubleTapHandler())
- return false;
-
- return _tapDelegate(1);
- }
-
bool GestureDetector.IOnGestureListener.OnDown(MotionEvent e)
{
SetStartingPosition(e);
+
+ if (HasAnyGestures())
+ {
+ // If we have any gestures to listen for, we need to return true to show we're interested in the rest
+ // of the events.
+ return true;
+ }
+
+ // Since we don't have any gestures we're listening for, we return false to show we're not interested
+ // and let parent controls have a whack at the events
return false;
}
@@ -119,10 +115,32 @@ namespace Xamarin.Forms.Platform.Android
if (_disposed)
return false;
- // optimization: do not wait for a second tap if there is no double tap handler
if (HasDoubleTapHandler())
+ {
+ // Because we have a handler for double-tap, we need to wait for
+ // OnSingleTapConfirmed (to verify it's really just a single tap) before running the delegate
return false;
+ }
+
+ // A single tap has occurred and there's no handler for double tap to worry about,
+ // so we can go ahead and run the delegate
+ return _tapDelegate(1);
+ }
+
+ bool GestureDetector.IOnDoubleTapListener.OnSingleTapConfirmed(MotionEvent e)
+ {
+ if (_disposed)
+ return false;
+
+ if (!HasDoubleTapHandler())
+ {
+ // We're not worried about double-tap, so OnSingleTap has already run the delegate
+ // there's nothing for us to do here
+ return false;
+ }
+ // Since there was a double-tap handler, we had to wait for OnSingleTapConfirmed;
+ // Now that we're sure it's a single tap, we can run the delegate
return _tapDelegate(1);
}
diff --git a/Xamarin.Forms.Platform.Android/InnerScaleListener.cs b/Xamarin.Forms.Platform.Android/InnerScaleListener.cs
index 4a6c658..76f7629 100644
--- a/Xamarin.Forms.Platform.Android/InnerScaleListener.cs
+++ b/Xamarin.Forms.Platform.Android/InnerScaleListener.cs
@@ -10,20 +10,16 @@ namespace Xamarin.Forms.Platform.Android
Action _pinchEndedDelegate;
Func<Point, bool> _pinchStartedDelegate;
- public InnerScaleListener(Func<float, Point, bool> pinchDelegate, Func<Point, bool> pinchStarted, Action pinchEnded)
+ public InnerScaleListener(PinchGestureHandler pinchGestureHandler)
{
- if (pinchDelegate == null)
- throw new ArgumentNullException("pinchDelegate");
-
- if (pinchStarted == null)
- throw new ArgumentNullException("pinchStarted");
-
- if (pinchEnded == null)
- throw new ArgumentNullException("pinchEnded");
+ if (pinchGestureHandler == null)
+ {
+ throw new ArgumentNullException(nameof(pinchGestureHandler));
+ }
- _pinchDelegate = pinchDelegate;
- _pinchStartedDelegate = pinchStarted;
- _pinchEndedDelegate = pinchEnded;
+ _pinchDelegate = pinchGestureHandler.OnPinch;
+ _pinchStartedDelegate = pinchGestureHandler.OnPinchStarted;
+ _pinchEndedDelegate = pinchGestureHandler.OnPinchEnded;
}
// This is needed because GestureRecognizer callbacks can be delayed several hundred milliseconds
diff --git a/Xamarin.Forms.Platform.Android/PanGestureHandler.cs b/Xamarin.Forms.Platform.Android/PanGestureHandler.cs
index 0837f63..32554d5 100644
--- a/Xamarin.Forms.Platform.Android/PanGestureHandler.cs
+++ b/Xamarin.Forms.Platform.Android/PanGestureHandler.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Platform.Android
@@ -66,5 +67,11 @@ namespace Xamarin.Forms.Platform.Android
}
return result;
}
+
+ public bool HasAnyGestures()
+ {
+ var view = GetView();
+ return view != null && view.GestureRecognizers.OfType<PanGestureRecognizer>().Any();
+ }
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/PinchGestureHandler.cs b/Xamarin.Forms.Platform.Android/PinchGestureHandler.cs
index c315b92..e5d3137 100644
--- a/Xamarin.Forms.Platform.Android/PinchGestureHandler.cs
+++ b/Xamarin.Forms.Platform.Android/PinchGestureHandler.cs
@@ -13,19 +13,11 @@ namespace Xamarin.Forms.Platform.Android
GetView = getView;
}
- public bool IsPinchSupported
- {
- get
- {
- View view = GetView();
- return view != null && view.GestureRecognizers.GetGesturesFor<PinchGestureRecognizer>().Any();
- }
- }
-
Func<View> GetView { get; }
// A View can have at most one pinch gesture, so we just need to look for one (or none)
- PinchGestureRecognizer PinchGesture => GetView()?.GestureRecognizers.GetGesturesFor<PinchGestureRecognizer>().FirstOrDefault();
+ PinchGestureRecognizer PinchGesture => GetView()?.GestureRecognizers.OfType<PinchGestureRecognizer>()
+ .FirstOrDefault();
public bool OnPinch(float scale, Point scalePoint)
{
@@ -39,7 +31,7 @@ namespace Xamarin.Forms.Platform.Android
return true;
var scalePointTransformed = new Point(scalePoint.X / view.Width, scalePoint.Y / view.Height);
- ((IPinchGestureController)pinchGesture).SendPinch(view, 1 + (scale - 1) * _pinchStartingScale, scalePointTransformed);
+ pinchGesture.SendPinch(view, 1 + (scale - 1) * _pinchStartingScale, scalePointTransformed);
return true;
}
@@ -52,7 +44,7 @@ namespace Xamarin.Forms.Platform.Android
return;
PinchGestureRecognizer pinchGesture = PinchGesture;
- ((IPinchGestureController)pinchGesture)?.SendPinchEnded(view);
+ pinchGesture?.SendPinchEnded(view);
}
public bool OnPinchStarted(Point scalePoint)
@@ -70,7 +62,7 @@ namespace Xamarin.Forms.Platform.Android
var scalePointTransformed = new Point(scalePoint.X / view.Width, scalePoint.Y / view.Height);
- ((IPinchGestureController)pinchGesture).SendPinchStarted(view, scalePointTransformed);
+ pinchGesture.SendPinchStarted(view, scalePointTransformed);
return true;
}
}
diff --git a/Xamarin.Forms.Platform.Android/Platform.cs b/Xamarin.Forms.Platform.Android/Platform.cs
index c0fc209..ebdf5e9 100644
--- a/Xamarin.Forms.Platform.Android/Platform.cs
+++ b/Xamarin.Forms.Platform.Android/Platform.cs
@@ -1055,11 +1055,9 @@ namespace Xamarin.Forms.Platform.Android
internal class DefaultRenderer : VisualElementRenderer<View>
{
bool _notReallyHandled;
- Dictionary<int, float> _minimumElevation = new Dictionary<int, float>();
public DefaultRenderer()
{
- ChildrenDrawingOrderEnabled = true;
}
readonly MotionEventHelper _motionEventHelper = new MotionEventHelper();
@@ -1069,11 +1067,6 @@ namespace Xamarin.Forms.Platform.Android
_notReallyHandled = true;
}
- internal void InvalidateMinimumElevation()
- {
- _minimumElevation = new Dictionary<int, float>();
- }
-
public override bool OnTouchEvent(MotionEvent e)
{
if (base.OnTouchEvent(e))
@@ -1128,31 +1121,8 @@ namespace Xamarin.Forms.Platform.Android
}
return result;
- }
-
- protected override int GetChildDrawingOrder(int childCount, int i)
- {
- //On Material design the button states use Elevation property, we need to make sure
- //we update the elevation of other controls to be over the previous one
- if (Forms.IsLollipopOrNewer)
- {
- if (!_minimumElevation.ContainsKey(i))
- {
- _minimumElevation[i] = GetChildAt(i).Elevation;
- }
-
- for (int j = 0; j < _minimumElevation.Count() - 1; j++)
{
- while (_minimumElevation[j] > _minimumElevation[j + 1])
- {
- _minimumElevation[j + 1] = _minimumElevation[j] + 1;
- GetChildAt(j + 1).Elevation = _minimumElevation[j + 1];
- }
- if (j == i)
- break;
}
- }
- return base.GetChildDrawingOrder(childCount, i);
}
}
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs
index 077cf15..1172f59 100644
--- a/Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs
@@ -106,12 +106,12 @@ namespace Xamarin.Forms.Platform.Android
await Control.UpdateBitmap(Element, previous);
}
- public override bool OnTouchEvent(MotionEvent e)
- {
- if (base.OnTouchEvent(e))
- return true;
-
- return _motionEventHelper.HandleMotionEvent(Parent, e);
- }
- }
+ public override bool OnTouchEvent(MotionEvent e)
+ {
+ if (base.OnTouchEvent(e))
+ return true;
+
+ return _motionEventHelper.HandleMotionEvent(Parent, e);
+ }
+ }
} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs
index b911656..d9f06c5 100644
--- a/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs
@@ -150,9 +150,24 @@ namespace Xamarin.Forms.Platform.Android
UpdateFooter();
UpdateIsSwipeToRefreshEnabled();
UpdateFastScrollEnabled();
+
+
}
}
+ internal void LongClickOn(AView viewCell)
+ {
+ if (Control == null)
+ {
+ return;
+ }
+
+ var position = Control.GetPositionForView(viewCell);
+ var id = Control.GetItemIdAtPosition(position);
+
+ _adapter.OnItemLongClick(Control, viewCell, position, id);
+ }
+
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ViewCellExtensions.cs b/Xamarin.Forms.Platform.Android/Renderers/ViewCellExtensions.cs
index 278e284..c7504ab 100644
--- a/Xamarin.Forms.Platform.Android/Renderers/ViewCellExtensions.cs
+++ b/Xamarin.Forms.Platform.Android/Renderers/ViewCellExtensions.cs
@@ -19,24 +19,5 @@ namespace Xamarin.Forms.Platform.Android
return false;
}
-
- public static void EnsureLongClickCancellation(this AView view, MotionEvent motionEvent, bool handled, VisualElement element)
- {
- if (view.IsDisposed())
- {
- return;
- }
-
- if (motionEvent.Action == MotionEventActions.Up && handled && view.LongClickable && element.IsInViewCell())
- {
- // In order for long presses/clicks (for opening context menus) to work in a ViewCell
- // which contains any Clickable Views (e.g., any with TapGestures associated, or Buttons)
- // the top-level container in the ViewCell has to be LongClickable; unfortunately, Android
- // cancels a pending long press/click during MotionEventActions.Up, which the View won't
- // get if the gesture listener has already processed it. So when all these conditions are
- // true, we need to go ahead and send the Up event to the View; if we don't, the context menu will open
- view.OnTouchEvent(motionEvent);
- }
- }
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/TapGestureHandler.cs b/Xamarin.Forms.Platform.Android/TapGestureHandler.cs
index 0dd6326..56d0641 100644
--- a/Xamarin.Forms.Platform.Android/TapGestureHandler.cs
+++ b/Xamarin.Forms.Platform.Android/TapGestureHandler.cs
@@ -41,6 +41,12 @@ namespace Xamarin.Forms.Platform.Android
return result;
}
+ public bool HasAnyGestures()
+ {
+ var view = GetView();
+ return view != null && view.GestureRecognizers.OfType<TapGestureRecognizer>().Any();
+ }
+
public IEnumerable<TapGestureRecognizer> TapGestureRecognizers(int count)
{
View view = GetView();
diff --git a/Xamarin.Forms.Platform.Android/VisualElementExtensions.cs b/Xamarin.Forms.Platform.Android/VisualElementExtensions.cs
index 268b3af..a39cc88 100644
--- a/Xamarin.Forms.Platform.Android/VisualElementExtensions.cs
+++ b/Xamarin.Forms.Platform.Android/VisualElementExtensions.cs
@@ -13,19 +13,5 @@ namespace Xamarin.Forms.Platform.Android
return renderer;
}
-
- public static bool ShouldBeMadeClickable(this View view)
- {
- for (var i = 0; i < view.GestureRecognizers.Count; i++)
- {
- IGestureRecognizer gesture = view.GestureRecognizers[i];
- if (gesture is TapGestureRecognizer || gesture is PinchGestureRecognizer || gesture is PanGestureRecognizer)
- {
- return true;
- }
- }
-
- return false;
- }
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/VisualElementPackager.cs b/Xamarin.Forms.Platform.Android/VisualElementPackager.cs
index 9178118..1d88662 100644
--- a/Xamarin.Forms.Platform.Android/VisualElementPackager.cs
+++ b/Xamarin.Forms.Platform.Android/VisualElementPackager.cs
@@ -120,7 +120,6 @@ namespace Xamarin.Forms.Platform.Android
(_renderer.View as ViewGroup)?.BringChildToFront(r.View);
}
}
- (_renderer as Platform.DefaultRenderer)?.InvalidateMinimumElevation();
}
void OnChildAdded(object sender, ElementEventArgs e)
diff --git a/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs b/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs
index 120cc97..098e85f 100644
--- a/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs
@@ -1,53 +1,66 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
-using System.Collections.Specialized;
using System.ComponentModel;
using Android.Support.V4.View;
using Android.Views;
using Xamarin.Forms.Internals;
+using Xamarin.Forms.Platform.Android.FastRenderers;
using AView = Android.Views.View;
namespace Xamarin.Forms.Platform.Android
{
- public abstract class VisualElementRenderer<TElement> : FormsViewGroup, IVisualElementRenderer, AView.IOnTouchListener, AView.IOnClickListener, IEffectControlProvider where TElement : VisualElement
+ public abstract class VisualElementRenderer<TElement> : FormsViewGroup, IVisualElementRenderer,
+ IEffectControlProvider where TElement : VisualElement
{
readonly List<EventHandler<VisualElementChangedEventArgs>> _elementChangedHandlers = new List<EventHandler<VisualElementChangedEventArgs>>();
- readonly Lazy<GestureDetector> _gestureDetector;
- readonly PanGestureHandler _panGestureHandler;
- readonly PinchGestureHandler _pinchGestureHandler;
- readonly TapGestureHandler _tapGestureHandler;
-
- NotifyCollectionChangedEventHandler _collectionChangeHandler;
-
VisualElementRendererFlags _flags = VisualElementRendererFlags.AutoPackage | VisualElementRendererFlags.AutoTrack;
string _defaultContentDescription;
bool? _defaultFocusable;
string _defaultHint;
int? _defaultLabelFor;
- InnerGestureListener _gestureListener;
+
VisualElementPackager _packager;
PropertyChangedEventHandler _propertyChangeHandler;
- Lazy<ScaleGestureDetector> _scaleDetector;
+
+ readonly GestureManager _gestureManager;
protected VisualElementRenderer() : base(Forms.Context)
{
- _tapGestureHandler = new TapGestureHandler(() => View);
- _panGestureHandler = new PanGestureHandler(() => View, Context.FromPixels);
- _pinchGestureHandler = new PinchGestureHandler(() => View);
-
- _gestureDetector =
- new Lazy<GestureDetector>(
- () =>
- new GestureDetector(
- _gestureListener =
- new InnerGestureListener(_tapGestureHandler.OnTap, _tapGestureHandler.TapGestureRecognizers, _panGestureHandler.OnPan, _panGestureHandler.OnPanStarted, _panGestureHandler.OnPanComplete)));
-
- _scaleDetector = new Lazy<ScaleGestureDetector>(
- () => new ScaleGestureDetector(Context, new InnerScaleListener(_pinchGestureHandler.OnPinch, _pinchGestureHandler.OnPinchStarted, _pinchGestureHandler.OnPinchEnded))
- );
+ _gestureManager = new GestureManager(this);
+ }
+
+ public override bool OnTouchEvent(MotionEvent e)
+ {
+ return _gestureManager.OnTouchEvent(e);
+ }
+
+ public override bool OnInterceptTouchEvent(MotionEvent ev)
+ {
+ if (!Enabled)
+ {
+ // If Enabled is false, prevent all the events from being dispatched to child Views
+ // and prevent them from being processed by this View as well
+ return true; // IOW, intercepted
+ }
+
+ return base.OnInterceptTouchEvent(ev);
+ }
+
+ public override bool DispatchTouchEvent(MotionEvent e)
+ {
+ if (InputTransparent)
+ {
+ // If the Element is InputTransparent, this ViewGroup will be marked InputTransparent
+ // If we're InputTransparent we should return false on all touch events without
+ // even bothering to send them to the child Views
+
+ return false; // IOW, not handled
+ }
+
+ return base.DispatchTouchEvent(e);
}
public TElement Element { get; private set; }
@@ -85,54 +98,6 @@ namespace Xamarin.Forms.Platform.Android
OnRegisterEffect(platformEffect);
}
- void AView.IOnClickListener.OnClick(AView v)
- {
- _tapGestureHandler.OnSingleClick();
- }
-
- public override bool OnInterceptTouchEvent(MotionEvent ev)
- {
- if (!Element.IsEnabled || (Element.InputTransparent && Element.IsEnabled))
- {
- return true;
- }
-
- return base.OnInterceptTouchEvent(ev);
- }
-
- bool AView.IOnTouchListener.OnTouch(AView v, MotionEvent e)
- {
- if (!Element.IsEnabled)
- return true;
-
- if (Element.InputTransparent)
- return false;
-
- var handled = false;
- if (_pinchGestureHandler.IsPinchSupported)
- {
- if (!_scaleDetector.IsValueCreated)
- ScaleGestureDetectorCompat.SetQuickScaleEnabled(_scaleDetector.Value, true);
- handled = _scaleDetector.Value.OnTouchEvent(e);
- }
-
- _gestureListener?.OnTouchEvent(e);
-
- if (_gestureDetector.IsValueCreated && _gestureDetector.Value.Handle == IntPtr.Zero)
- {
- // This gesture detector has already been disposed, probably because it's on a cell which is going away
- return handled;
- }
-
- // It's very important that the gesture detection happen first here
- // if we check handled first, we might short-circuit and never check for tap/pan
- handled = _gestureDetector.Value.OnTouchEvent(e) || handled;
-
- v.EnsureLongClickCancellation(e, handled, Element);
-
- return handled;
- }
-
VisualElement IVisualElementRenderer.Element => Element;
event EventHandler<VisualElementChangedEventArgs> IVisualElementRenderer.ElementChanged
@@ -183,7 +148,6 @@ namespace Xamarin.Forms.Platform.Android
if (oldElement != null)
{
oldElement.PropertyChanged -= _propertyChangeHandler;
- UnsubscribeGestureRecognizers(oldElement);
}
// element may be allowed to be passed as null in the future
@@ -198,19 +162,12 @@ namespace Xamarin.Forms.Platform.Android
_propertyChangeHandler = OnElementPropertyChanged;
element.PropertyChanged += _propertyChangeHandler;
- SubscribeGestureRecognizers(element);
if (oldElement == null)
{
- SetOnClickListener(this);
- SetOnTouchListener(this);
SoundEffectsEnabled = false;
}
- // must be updated AFTER SetOnClickListener is called
- // SetOnClickListener implicitly calls Clickable = true
- UpdateGestureRecognizers(true);
-
OnElementChanged(new ElementChangedEventArgs<TElement>(oldElement, element));
if (AutoPackage && _packager == null)
@@ -263,18 +220,6 @@ namespace Xamarin.Forms.Platform.Android
_packager = null;
}
- if (_scaleDetector != null && _scaleDetector.IsValueCreated)
- {
- _scaleDetector.Value.Dispose();
- _scaleDetector = null;
- }
-
- if (_gestureListener != null)
- {
- _gestureListener.Dispose();
- _gestureListener = null;
- }
-
if (ManageNativeControlLifetime)
{
int count = ChildCount;
@@ -290,7 +235,6 @@ namespace Xamarin.Forms.Platform.Android
if (Element != null)
{
Element.PropertyChanged -= _propertyChangeHandler;
- UnsubscribeGestureRecognizers(Element);
if (Platform.GetRenderer(Element) == this)
Platform.SetRenderer(Element, null);
@@ -328,6 +272,7 @@ namespace Xamarin.Forms.Platform.Android
SetFocusable();
else if (e.PropertyName == VisualElement.InputTransparentProperty.PropertyName)
UpdateInputTransparent();
+
ElementPropertyChanged?.Invoke(this, e);
}
@@ -441,11 +386,6 @@ namespace Xamarin.Forms.Platform.Android
element.SendViewInitialized(nativeView);
}
- void HandleGestureRecognizerCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
- {
- UpdateGestureRecognizers();
- }
-
void IVisualElementRenderer.SetLabelFor(int? id)
{
if (_defaultLabelFor == null)
@@ -453,47 +393,5 @@ namespace Xamarin.Forms.Platform.Android
LabelFor = (int)(id ?? _defaultLabelFor);
}
-
- void SubscribeGestureRecognizers(VisualElement element)
- {
- var view = element as View;
- if (view == null)
- return;
-
- if (_collectionChangeHandler == null)
- _collectionChangeHandler = HandleGestureRecognizerCollectionChanged;
-
- var observableCollection = (ObservableCollection<IGestureRecognizer>)view.GestureRecognizers;
- observableCollection.CollectionChanged += _collectionChangeHandler;
- }
-
- void UnsubscribeGestureRecognizers(VisualElement element)
- {
- var view = element as View;
- if (view == null || _collectionChangeHandler == null)
- return;
-
- var observableCollection = (ObservableCollection<IGestureRecognizer>)view.GestureRecognizers;
- observableCollection.CollectionChanged -= _collectionChangeHandler;
- }
-
- void UpdateClickable(bool force = false)
- {
- var view = Element as View;
- if (view == null)
- return;
-
- bool newValue = view.ShouldBeMadeClickable();
- if (force || newValue)
- Clickable = newValue;
- }
-
- void UpdateGestureRecognizers(bool forceClick = false)
- {
- if (View == null)
- return;
-
- UpdateClickable(forceClick);
- }
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj b/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj
index 91f5db7..8539ddc 100644
--- a/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj
+++ b/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj
@@ -125,7 +125,7 @@
<Compile Include="ExportCellAttribute.cs" />
<Compile Include="ExportImageSourceHandlerAttribute.cs" />
<Compile Include="ExportRendererAttribute.cs" />
- <Compile Include="FastRenderers\GestureManager.cs" />
+ <Compile Include="GestureManager.cs" />
<Compile Include="FastRenderers\LabelRenderer.cs" />
<Compile Include="FastRenderers\VisualElementRenderer.cs" />
<Compile Include="Flags.cs" />