diff --git a/PanCardView/CardsView.cs b/PanCardView/CardsView.cs index 8839d6b..51d2b41 100644 --- a/PanCardView/CardsView.cs +++ b/PanCardView/CardsView.cs @@ -135,6 +135,7 @@ public class CardsView : AbsoluteLayout private readonly Dictionary> _viewsGestureCounter = new Dictionary>(); private readonly List _timeDiffItems = new List(); private readonly ViewsInUseSet _viewsInUse = new ViewsInUseSet(); + private readonly InteractionQueue _interactions = new InteractionQueue(); private IEnumerable _prevViews = Enumerable.Empty(); private IEnumerable _nextViews = Enumerable.Empty(); @@ -152,7 +153,6 @@ public class CardsView : AbsoluteLayout private bool _hasRenderer; private bool? _isPortraitOrientation; private bool? _shouldScrollParent; - private Guid _gestureId; private DateTime _lastPanTime; private CancellationTokenSource _slideshowTokenSource; @@ -670,7 +670,7 @@ private void StartAutoNavigation(View view, Guid animationId, AnimationDirection { if (view != null) { - _gestureId = animationId; + _interactions.Add(animationId, InteractionType.Animation); IsAutoNavigating = true; if (IsPanInCourse) { @@ -696,9 +696,10 @@ private void EndAutoNavigation(View view, Guid animationId, AnimationDirection a } } IsAutoNavigating = false; - var isProcessingNow = _gestureId != animationId; + var isProcessingNow = !_interactions.CheckLastId(animationId); RemoveRedundantChildren(isProcessingNow); FireAutoNavigationEnded(animationDirection != AnimationDirection.Prev); + _interactions.Remove(animationId); } private AnimationDirection GetAutoNavigateAnimationDirection() @@ -754,7 +755,9 @@ private void OnTouchStarted() _inCoursePanDelay = int.MaxValue; } - var gestureId = _gestureId = Guid.NewGuid(); + var gestureId = Guid.NewGuid(); + _interactions.Add(gestureId, InteractionType.Gesture); + FirePanStarted(); IsPanRunning = true; _isPanEndRequested = false; @@ -796,7 +799,7 @@ private async void OnTouchEnded(bool? isSwiped) } _lastPanTime = DateTime.Now; - var gestureId = _gestureId; + var gestureId = _interactions.GetFirstId(InteractionType.Gesture); _isPanEndRequested = true; var absDiff = Abs(CurrentDiff); @@ -858,8 +861,9 @@ await Task.WhenAll( FirePanEnded(isNextSelected, index, diff); - RemoveRangeViewsInUse(gestureId); - var isProcessingNow = gestureId != _gestureId; + var isProcessingNow = !_interactions.CheckLastId(gestureId); + RemoveRangeViewsInUse(gestureId, isProcessingNow); + if (!isProcessingNow) { IsPanRunning = false; @@ -877,6 +881,8 @@ await Task.WhenAll( RemoveRedundantChildren(isProcessingNow); _inCoursePanDelay = 0; + + _interactions.Remove(gestureId); } private bool? CheckSwipe() @@ -1320,14 +1326,14 @@ private void AddRangeViewsInUse(Guid gestureId) } } - private void RemoveRangeViewsInUse(Guid gestureId) + private void RemoveRangeViewsInUse(Guid gestureId, bool isProcessingNow) { lock (_viewsInUseLocker) { foreach (var view in _viewsGestureCounter[gestureId]) { _viewsInUse.Remove(view); - if (_gestureId != gestureId && !_viewsInUse.Contains(view)) + if (isProcessingNow && !_viewsInUse.Contains(view)) { CleanView(view); } diff --git a/PanCardView/Enums/InteractionType.cs b/PanCardView/Enums/InteractionType.cs new file mode 100644 index 0000000..a1f9381 --- /dev/null +++ b/PanCardView/Enums/InteractionType.cs @@ -0,0 +1,14 @@ +using System; + +using Xamarin.Forms; + +namespace PanCardView.Enums +{ + [Flags] + public enum InteractionType + { + Gesture = -1, + Animation = 1 + } +} + diff --git a/PanCardView/PanCardView.csproj b/PanCardView/PanCardView.csproj index 47e100e..e89f55e 100644 --- a/PanCardView/PanCardView.csproj +++ b/PanCardView/PanCardView.csproj @@ -50,6 +50,9 @@ + + + diff --git a/PanCardView/Utility/InteractionItem.cs b/PanCardView/Utility/InteractionItem.cs new file mode 100644 index 0000000..382afcc --- /dev/null +++ b/PanCardView/Utility/InteractionItem.cs @@ -0,0 +1,10 @@ +using System; +using PanCardView.Enums; +namespace PanCardView.Utility +{ + public struct InteractionItem + { + public Guid Id { get; set; } + public InteractionType Type { get; set; } + } +} diff --git a/PanCardView/Utility/InteractionQueue.cs b/PanCardView/Utility/InteractionQueue.cs new file mode 100644 index 0000000..527a836 --- /dev/null +++ b/PanCardView/Utility/InteractionQueue.cs @@ -0,0 +1,51 @@ +using System; +using PanCardView.Enums; +using System.Collections.Generic; +using System.Linq; + +namespace PanCardView.Utility +{ + public sealed class InteractionQueue + { + private readonly List _queue = new List(); + private readonly object _queueLocker = new object(); + + public Guid GetFirstId(InteractionType type = InteractionType.Gesture | InteractionType.Animation) + { + lock(_queueLocker) + { + return _queue.FirstOrDefault(i => type.HasFlag(i.Type)).Id; + } + } + + public void Add(Guid id, InteractionType type) + { + lock (_queueLocker) + { + _queue.Add(new InteractionItem + { + Id = id, + Type = type + }); + } + } + + public void Remove(Guid id) + { + lock (_queueLocker) + { + var item = _queue.FirstOrDefault(i => i.Id == id); + _queue.Remove(item); + } + } + + public bool CheckLastId(Guid id, InteractionType type = InteractionType.Gesture | InteractionType.Animation) + { + lock(_queueLocker) + { + return _queue.LastOrDefault(i => type.HasFlag(i.Type)).Id == id; + } + } + } +} +