13

我一直在涉足新的 iOS 7 自定义转换 API,并查看了我能找到的所有教程/文档,但我似乎无法为我的特定场景弄清楚这些东西。

所以基本上我想要实现的是一个视图上的 UIPanGestureRecognizer,我将向上滑动并转换到一个 VC,其视图将从底部向上滑动,而当我将手指向上拖动时,当前视图会向上滑动。

没有交互转换我没有问题,但是一旦我实现了交互(平移手势),我似乎无法完成转换。

下面是来自 VC 的符合 UIViewControllerTransitionDelegate 的相关代码,这是出售动画控制器所需的:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"Swipe"]) {
        NSLog(@"PREPARE FOR SEGUE METHOD CALLED");

        UIViewController *toVC = segue.destinationViewController;
        [interactionController wireToViewController:toVC];
        toVC.transitioningDelegate = self;
        toVC.modalPresentationStyle = UIModalPresentationCustom;
      }
}

#pragma mark UIViewControllerTransition Delegate Methods

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:  (UIViewController *)presented                                                                   presentingController:  (UIViewController *)presenting sourceController:(UIViewController *)source {
    NSLog(@"PRESENTING ANIMATION CONTROLLER CALLED");

    SwipeDownPresentationAnimationController *transitionController = [SwipeDownPresentationAnimationController new];
    return transitionController;
}

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
    NSLog(@"DISMISS ANIMATION CONTROLLER CALLED");

    DismissAnimatorViewController *transitionController = [DismissAnimatorViewController new];
    return transitionController;
}

- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator {
    NSLog(@"Interaction controller for dimiss method caled");

    return interactionController.interactionInProgress ? interactionController:nil;
}

注意:交互滑动仅用于关闭 VC,这就是它在interactionControllerForDismissal 方法中的原因

这是解除动画的代码,当我点击按钮解除它时,它工作正常:

#import "DismissAnimatorViewController.h"

@implementation DismissAnimatorViewController

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
    return 1.0;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
    NSTimeInterval duration = [self transitionDuration:transitionContext];

    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    CGRect initialFrameFromVC = [transitionContext initialFrameForViewController:fromVC];

    UIView *containerView = [transitionContext containerView];

    CGRect screenBounds = [[UIScreen mainScreen] bounds];
    NSLog(@"The screen bounds is :%@", NSStringFromCGRect(screenBounds));
    toVC.view.frame = CGRectOffset(initialFrameFromVC, 0, screenBounds.size.height);
    toVC.view.alpha = 0.2;

    CGRect pushedPresentingFrame = CGRectOffset(initialFrameFromVC, 0, -screenBounds.size.height);

    [containerView addSubview:toVC.view];

    [UIView animateWithDuration:duration
                          delay:0
         usingSpringWithDamping:0.6
          initialSpringVelocity:0
                        options:UIViewAnimationOptionCurveEaseIn
                     animations:^{
                         fromVC.view.frame = pushedPresentingFrame;
                         fromVC.view.alpha = 0.2;
                         toVC.view.frame = initialFrameFromVC;
                         toVC.view.alpha = 1.0;
                     } completion:^(BOOL finished) {
                         [transitionContext completeTransition:YES];
                     }];
}

@end

这是用作交互控制器的 UIPercentDrivenInteractiveTransition 子类的代码:

#import "SwipeInteractionController.h"

@implementation SwipeInteractionController {
    BOOL _shouldCompleteTransition;
    UIViewController *_viewController;
}

- (void)wireToViewController:(UIViewController *)viewController {
    _viewController = viewController;
    [self prepareGestureRecognizerInView:_viewController.view];
}

- (void)prepareGestureRecognizerInView:(UIView*)view {
    UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
    gesture.minimumNumberOfTouches = 1.0;

    [view addGestureRecognizer:gesture];
}

- (CGFloat)completionSpeed {
    return 1 - self.percentComplete;
    NSLog(@"PERCENT COMPLETE:%f",self.percentComplete);
}

- (void)handleGesture:(UIPanGestureRecognizer*)gestureRecognizer {
//    CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view.superview];
    CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view.superview];

    switch (gestureRecognizer.state) {
        case UIGestureRecognizerStateBegan:
            // 1. Start an interactive transition!
            self.interactionInProgress = YES;
            [_viewController dismissViewControllerAnimated:YES completion:nil];
            break;
        case UIGestureRecognizerStateChanged: {
            // 2. compute the current position
            CGFloat fraction = fabsf(translation.y / 568);
            NSLog(@"Fraction is %f",fraction);
            fraction = fminf(fraction, 1.0);
            fraction = fmaxf(fraction, 0.0);
            // 3. should we complete?
            _shouldCompleteTransition = (fraction > 0.23);
            // 4. update the animation controller
            [self updateInteractiveTransition:fraction];
            NSLog(@"Percent complete:%f",self.percentComplete);
            break;
        }
        case UIGestureRecognizerStateEnded:
        case UIGestureRecognizerStateCancelled: {
            // 5. finish or cancel
            NSLog(@"UI GESTURE RECOGNIZER STATE CANCELED");
            self.interactionInProgress = NO;
            if (!_shouldCompleteTransition || gestureRecognizer.state == UIGestureRecognizerStateCancelled) {
                [self cancelInteractiveTransition];
                NSLog(@"Interactive Transition is cancled.");
                }
            else {
                NSLog(@"Interactive Transition is FINISHED");
                [self finishInteractiveTransition];
            }
            break;
        }
        default:
            NSLog(@"Default is being called");
            break;
    }
}

@end

再一次,当我现在运行代码并且我没有一直滑动以有目的地取消转换时,我只是得到一个闪光并呈现我想要滑动到的视图控制器。无论转换是完成还是取消,都会发生这种情况。

但是,当我通过按钮关闭时,我得到了动画视图控制器中指定的过渡。

4

2 回答 2

22

我可以在这里看到几个问题 - 尽管我不能确定这些是否会解决您的问题!

首先,您的动画控制器的 UIView 动画完成块具有以下内容:

[transitionContext completeTransition:YES];

而它应该根据交互控制器的结果返回完成,如下所示:

[transitionContext completeTransition:![transitionContext transitionWasCancelled]]

另外,我发现如果您告诉UIPercentDrivenInteractiveTransition100% 完成转换,它不会调用动画控制器完成块。作为一种解决方法,我将其限制在 ~99.9%

https://github.com/ColinEberhardt/VCTransitionsLibrary/issues/4

我在这里创建了许多示例交互和动画控制器,您可能会发现它们很有用:

https://github.com/ColinEberhardt/VCTransitionsLibrary

于 2013-10-02T09:03:49.067 回答
2

我有同样的问题。我尝试了上述修复和其他修复,但没有任何效果。然后我偶然发现了https://github.com/MrAlek/AWPercentDrivenInteractiveTransition,它修复了所有问题。

将其添加到项目后,只需替换UIPercentDrivenInteractiveTransitionAWPercentDrivenInteractiveTransition.

此外,您必须在开始交互式过渡之前设置动画师。UIViewControllerAnimatedTransitioning就我而言,我对and使用相同的类UIViewControllerInteractiveTransitioning,所以我只是在init()

init() {
    super.init()
    self.animator = self
}
于 2015-04-23T21:48:53.587 回答