private void HandlePointerReleased(object sender, PointerRoutedEventArgs e) { if (!_isPointerDown) { return; } RenderGrid.ReleasePointerCapture(e.Pointer); _isPointerDown = false; _isSwiping = false; _sw0.Stop(); // If it is not a valid swipe no need to go further if (_swipeDir == SwipeDirection.None) { return; } var currPoint = e.GetCurrentPoint(RenderGrid).Position; if (currPoint.X.IsCloseTo(_swipeStartPoint.X)) { return; } var currSwipeDir = currPoint.X > _swipeStartPoint.X ? SwipeDirection.Right : SwipeDirection.Left; if (_swipeDir != currSwipeDir) { _revealPercent = _swipeDir == SwipeDirection.Left ? SwipeRightEnd : SwipeLeftEnd; _currOffsetX = _swipeDir == SwipeDirection.Left ? MaxOffsetX : MinOffsetX; } else { // Since the user has completed interaction for the current swipe, check if it is a valid swipe. // If yes, then animate the shape to its final destination otherwise animate to return to its // initial location. var diffX = Math.Abs(currPoint.X - _swipeStartPoint.X); var swipePercent = Math.Min((float)(diffX * 2 / _rootSize.Width), 1f); var isValidSwipe = (swipePercent > SwipeThreshold) || ((_sw0.ElapsedMilliseconds < SwipeThresholdDuration.TotalMilliseconds) && ((float)diffX > SwipeDistanceThreshold)); slideDirection = SlideDirection.RightToLeft; var durationPercent = isValidSwipe ? (1 - swipePercent) : swipePercent; _a0 = TimeSpan.FromMilliseconds(Math.Max(1, DefaultGeometryAnimDuration * durationPercent)); _a1 = TimeSpan.FromMilliseconds(Math.Max(1, DefaultOffsetAnimDuration * swipePercent)); switch (_swipeDir) { case SwipeDirection.Left: _swipeStartX = swipePercent; _startOffsetX = Lerp(MaxOffsetX, MinOffsetX, EaseOut(swipePercent)); if (isValidSwipe) { _swipeEndX = SwipeLeftEnd; // Update to the next valid index _nextLeftIndex = _selectedIndex <= 2 ? -1 : _selectedIndex - 1; _nextRightIndex = _selectedIndex; _endOffsetX = MinOffsetX; } else { _swipeEndX = SwipeRightEnd; _endOffsetX = MaxOffsetX; _nextLeftIndex = _swipeLeftIndex; _nextRightIndex = _swipeRightIndex; } break; case SwipeDirection.Right: _swipeStartX = 1 - swipePercent; _startOffsetX = Lerp(MinOffsetX, MaxOffsetX, EaseOut(swipePercent)); if (isValidSwipe) { _swipeEndX = SwipeRightEnd; // Update to the next valid index _nextLeftIndex = _selectedIndex; _nextRightIndex = _selectedIndex >= MaxLayerCount ? -1 : _selectedIndex + 1; _endOffsetX = MaxOffsetX; } else { _swipeEndX = SwipeLeftEnd; _endOffsetX = MinOffsetX; _nextLeftIndex = _swipeLeftIndex; _nextRightIndex = _swipeRightIndex; } break; } _sw1.Start(); _sw2.Start(); } }