summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs
diff options
context:
space:
mode:
authorE.Z. Hart <hartez@users.noreply.github.com>2017-09-15 12:49:19 -0600
committerRui Marinho <me@ruimarinho.net>2017-09-15 20:28:38 +0100
commitfc3ad54edbe4f7e33e2d8c4f9bc217b93dd62ecc (patch)
treee63d0d922f62198993735c34811ede1a0d69f1b8 /Xamarin.Forms.Platform.Android/VisualElementRenderer.cs
parentd1bf93be200b3d3c48d0d292bf455f444485d8f9 (diff)
downloadxamarin-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.cs180
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