public CustomPanAnimation(UIView view) { superViewWidth = view.Superview.Frame.Width; xOffset = superViewWidth - view.Frame.Width; var recognizer = new UIPanGestureRecognizer((UIPanGestureRecognizer obj) => { switch (obj.State) { case UIGestureRecognizerState.Began: animator = new UIViewPropertyAnimator(1, UIViewAnimationCurve.EaseOut, () => { var velocity = obj.VelocityInView(view); if (velocity.X < 0) { direction = -1; } else { direction = 1; } var frame = view.Frame; frame.Offset(direction * xOffset, 0); view.Frame = frame; }); animator.PauseAnimation(); progressWhenInterrupted = animator.FractionComplete; break; case UIGestureRecognizerState.Changed: var translation = obj.TranslationInView(view); animator.FractionComplete = (direction * translation.X / xOffset) + progressWhenInterrupted; break; case UIGestureRecognizerState.Ended: if (Math.Abs(animator.FractionComplete) < 0.3) { animator.Reversed = true; } var timing = new UICubicTimingParameters(UIViewAnimationCurve.EaseOut); animator.ContinueAnimation(timing, 0); break; } }); view.UserInteractionEnabled = true; view.AddGestureRecognizer(recognizer); }
public CustomSlideAnimation(UIView view, Axis axis) { superViewWidth = view.Superview.Frame.Width; superViewHeight = view.Superview.Frame.Height; xOffset = superViewWidth - view.Frame.Width; yOffset = superViewHeight - view.Frame.Height - 40; var recognizer = new UIPanGestureRecognizer((UIPanGestureRecognizer obj) => { switch (obj.State) { case UIGestureRecognizerState.Began: animator = new UIViewPropertyAnimator(1, UIViewAnimationCurve.EaseOut, () => { var velocity = obj.VelocityInView(view); if (axis == Axis.X && velocity.X < 0) { direction = -1; } else if (axis == Axis.Y && velocity.Y < 0) { direction = -1; } else { direction = 1; } var frame = view.Frame; if (axis == Axis.Y) { frame.Offset(0, direction * yOffset); } else { frame.Offset(direction * xOffset, 0); } view.Frame = frame; }); animator.PauseAnimation(); progressWhenInterrupted = animator.FractionComplete; break; case UIGestureRecognizerState.Changed: var translation = obj.TranslationInView(view); if (axis == Axis.Y) { animator.FractionComplete = (direction * translation.Y / yOffset) + progressWhenInterrupted; } else { animator.FractionComplete = (direction * translation.X / xOffset) + progressWhenInterrupted; } break; case UIGestureRecognizerState.Ended: animator.PauseAnimation(); break; } }); view.UserInteractionEnabled = true; view.AddGestureRecognizer(recognizer); }
void Panned(object r) { var recognizer = r as UIPanGestureRecognizer; switch (recognizer.State) { case UIGestureRecognizerState.Began: StartAnimationIfNeeded(); animator.PauseAnimation(); animationProgress = animator.FractionComplete; break; case UIGestureRecognizerState.Changed: var fraction = -recognizer.TranslationInView(momentumView).Y / closedTransform.y0; if (isOpen) { fraction *= -1; } if (animator.Reversed) { fraction *= -1; } animator.FractionComplete = fraction + animationProgress; break; case UIGestureRecognizerState.Ended: case UIGestureRecognizerState.Cancelled: var yVelocity = recognizer.VelocityInView(momentumView).Y; var shouldClose = yVelocity > 0; // todo: should use projection instead if (yVelocity == 0) { animator.ContinueAnimation(parameters: null, durationFactor: 0); break; } if (isOpen) { if (!shouldClose && !animator.Reversed) { animator.Reversed = !animator.Reversed; } if (shouldClose && animator.Reversed) { animator.Reversed = !animator.Reversed; } } else { if (shouldClose && !animator.Reversed) { animator.Reversed = !animator.Reversed; } if (!shouldClose && animator.Reversed) { animator.Reversed = !animator.Reversed; } } var fractionRemaining = 1 - animator.FractionComplete; var distanceRemaining = fractionRemaining * closedTransform.y0; if (distanceRemaining == 0) { animator.ContinueAnimation(null, 0); break; } var relativeVelocity = NMath.Min(NMath.Abs(yVelocity) / distanceRemaining, 30); var timingParameters = UISpringTiming.MakeTimingParameters(damping: 0.8f, response: 0.3f, initialVelocity: new CGVector(dx: relativeVelocity, dy: relativeVelocity)); var preferredDuration = new UIViewPropertyAnimator(duration: 0, parameters: timingParameters).Duration; var durationFactor = preferredDuration / animator.Duration; animator.ContinueAnimation(parameters: timingParameters, durationFactor: (nfloat)durationFactor); break; default: break; } }