예제 #1
0
        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);
        }
    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;
        }
    }