From cc0eb5ba4326de96a52c0318a61b89c3bcb098e5 Mon Sep 17 00:00:00 2001 From: adrianknight89 Date: Tue, 3 Jan 2017 05:30:35 -0600 Subject: [iOS] Prevent multiple ListView cells from being swiped simultaneously (#578) * disable multiple cell swipe * add sample code * refactored * convert to weakreference * remove null setting * change weakreference setting place * remove if * revert isopen changes * add instructions --- .../Bugzilla43735.cs | 61 ++++++++++++++++++++++ .../Xamarin.Forms.Controls.Issues.Shared.projitems | 1 + .../ContextScrollViewDelegate.cs | 31 +++++++++-- 3 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla43735.cs diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla43735.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla43735.cs new file mode 100644 index 00000000..5f247eaf --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla43735.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; + +#if UITEST +using Xamarin.UITest; +using NUnit.Framework; +#endif + +namespace Xamarin.Forms.Controls.Issues +{ + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Bugzilla, 43735, "Multiple Swipe on ContextActions", PlatformAffected.iOS)] + public class Bugzilla43735 : TestContentPage // or TestMasterDetailPage, etc ... + { + protected override void Init() + { + var stackLayout = new StackLayout(); + + var l = new Label + { + Text = "Swipe multiple cells at the same time. Only one cell should show its context actions." + }; + stackLayout.Children.Add(l); + + var list = new List(); + for (var i = 0; i < 20; i++) + list.Add(i); + + var listView = new ListView + { + ItemsSource = list, + ItemTemplate = new DataTemplate(() => + { + var label = new Label(); + label.SetBinding(Label.TextProperty, new Binding(".")); + + return new ViewCell + { + View = new ContentView + { + Content = label, + }, + ContextActions = { new MenuItem + { + Text = "Action" + }, + new MenuItem + { + Text = "Delete", + IsDestructive = true + } } + }; + }) + }; + stackLayout.Children.Add(listView); + + Content = stackLayout; + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems index c5d93821..4820bae3 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems @@ -139,6 +139,7 @@ + diff --git a/Xamarin.Forms.Platform.iOS/ContextScrollViewDelegate.cs b/Xamarin.Forms.Platform.iOS/ContextScrollViewDelegate.cs index 14f95a73..9d5debf1 100644 --- a/Xamarin.Forms.Platform.iOS/ContextScrollViewDelegate.cs +++ b/Xamarin.Forms.Platform.iOS/ContextScrollViewDelegate.cs @@ -45,7 +45,7 @@ namespace Xamarin.Forms.Platform.iOS GlobalCloseContextGestureRecognizer _globalCloser; bool _isDisposed; - + static WeakReference s_scrollViewBeingScrolled; UITableView _table; public ContextScrollViewDelegate(UIView container, List buttons, bool isOpen) @@ -72,6 +72,11 @@ namespace Xamarin.Forms.Platform.iOS public override void DraggingStarted(UIScrollView scrollView) { + if (ShouldIgnoreScrolling(scrollView)) + return; + + s_scrollViewBeingScrolled = new WeakReference(scrollView); + if (!IsOpen) SetButtonsShowing(true); @@ -90,6 +95,9 @@ namespace Xamarin.Forms.Platform.iOS public override void Scrolled(UIScrollView scrollView) { + if (ShouldIgnoreScrolling(scrollView)) + return; + var width = _finalButtonSize; var count = _buttons.Count; @@ -116,10 +124,9 @@ namespace Xamarin.Forms.Platform.iOS SetButtonsShowing(false); RestoreHighlight(scrollView); + s_scrollViewBeingScrolled = null; ClearCloserRecognizer(scrollView); - - if (ClosedCallback != null) - ClosedCallback(); + ClosedCallback?.Invoke(); } } @@ -131,6 +138,9 @@ namespace Xamarin.Forms.Platform.iOS public override void WillEndDragging(UIScrollView scrollView, PointF velocity, ref PointF targetContentOffset) { + if (ShouldIgnoreScrolling(scrollView)) + return; + var width = ButtonsWidth; var x = targetContentOffset.X; var parentThreshold = scrollView.Frame.Width * .4f; @@ -187,6 +197,19 @@ namespace Xamarin.Forms.Platform.iOS } } + static bool ShouldIgnoreScrolling(UIScrollView scrollView) + { + if (s_scrollViewBeingScrolled == null) + return false; + + UIScrollView scrollViewBeingScrolled; + if (!s_scrollViewBeingScrolled.TryGetTarget(out scrollViewBeingScrolled) || ReferenceEquals(scrollViewBeingScrolled, scrollView)) + return false; + + scrollView.SetContentOffset(new PointF(0, 0), false); + return true; + } + protected override void Dispose(bool disposing) { if (_isDisposed) -- cgit v1.2.3