diff options
author | E.Z. Hart <hartez@users.noreply.github.com> | 2017-09-15 12:49:19 -0600 |
---|---|---|
committer | Rui Marinho <me@ruimarinho.net> | 2017-09-15 20:28:38 +0100 |
commit | fc3ad54edbe4f7e33e2d8c4f9bc217b93dd62ecc (patch) | |
tree | e63d0d922f62198993735c34811ede1a0d69f1b8 /Xamarin.Forms.Platform.Android/VisualElementRenderer.cs | |
parent | d1bf93be200b3d3c48d0d292bf455f444485d8f9 (diff) | |
download | xamarin-forms-fc3ad54edbe4f7e33e2d8c4f9bc217b93dd62ecc.tar.gz xamarin-forms-fc3ad54edbe4f7e33e2d8c4f9bc217b93dd62ecc.tar.bz2 xamarin-forms-fc3ad54edbe4f7e33e2d8c4f9bc217b93dd62ecc.zip |
[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/VisualElementRenderer.cs')
-rw-r--r-- | Xamarin.Forms.Platform.Android/VisualElementRenderer.cs | 180 |
1 files changed, 39 insertions, 141 deletions
diff --git a/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs b/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs index 120cc972..098e85f6 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 |