dismissModalViewController with transition:从左到右

时间:2012-07-10 11:34:07

标签: iphone animation uiviewanimationtransition catransition

我正在使用一种不错的方法来解雇我的模态视图控制器:

[self dismissModalViewControllerWithTransition:2];

从左到右进行幻灯片转换,就像导航控制器弹出视图一样。

由于此方法是非公开方法,因此Apple不会接受它。如何在我的代码中编程这种类型的动画(从左到右滑动,关闭模态视图,从右到左滑动以呈现模态视图)?

提前致谢

3 个答案:

答案 0 :(得分:42)

我接受了Safecase的回答,但我想在此发布我的最终解决方案:

1)为了呈现具有从右到左过渡的模态视图控制器,我写了以下方法:

-(void) presentModalView:(UIViewController *)controller {
    CATransition *transition = [CATransition animation];
    transition.duration = 0.35;
    transition.timingFunction =
    [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionMoveIn;
    transition.subtype = kCATransitionFromRight;

    // NSLog(@"%s: self.view.window=%@", _func_, self.view.window);
    UIView *containerView = self.view.window;
    [containerView.layer addAnimation:transition forKey:nil];
    [self presentModalViewController:controller animated:NO];
}

2)使用从左到右的幻灯片转换关闭模态视图:

-(void) dismissMe {
    CATransition *transition = [CATransition animation];
    transition.duration = 0.35;
    transition.timingFunction =
    [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionMoveIn;
    transition.subtype = kCATransitionFromLeft;

    // NSLog(@"%s: controller.view.window=%@", _func_, controller.view.window);
    UIView *containerView = self.view.window;
    [containerView.layer addAnimation:transition forKey:nil];

    [self dismissModalViewControllerAnimated:NO];
}

谢谢你们!

答案 1 :(得分:7)

试试这个:

我认为您正在从视图控制器1中解除视图控制器2.在视图控制器2中,您正在使用此

[self  dismissModalViewControlleAnimated: NO]];

现在在第一个视图控制器中,在viewWillAppear:方法中添加代码

CATransition *animation = [CATransition animation];

[animation setDelegate:self];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];

[animation setDuration:0.50];
[animation setTimingFunction:
 [CAMediaTimingFunction functionWithName:
  kCAMediaTimingFunctionEaseInEaseOut]];


[self.view.layer addAnimation:animation forKey:kCATransition];

答案 2 :(得分:1)

下面的Swift 4 ModalService类是一个预先打包的灵活解决方案,可以放入项目中并从任何需要的地方调用。此类将模态视图从指定方向置于当前视图的顶部,然后将其移出以在其退出时显示其后面的原始视图。如果当前正在显示presentingViewController并且您已创建并希望显示modalViewController,则只需致电:

ModalService.present(modalViewController, presenter: presentingViewController)

然后,要解雇,请致电:

ModalService.dismiss(modalViewController)

当然可以从modalViewController本身调用ModalService.dismiss(self)。请注意,不必从presentsViewController调用dismissing,也不需要知道或引用原始的presentationViewController。

该类提供合理的默认值,包括从右侧和左侧转换模态视图。可以通过传递方向来定制此转换方向,该方向可以针对进入和退出进行自定义:

ModalService.present(modalViewController, presenter: presentingViewController, enterFrom: .left)

ModalService.dismiss(self, exitTo: .left)

可以将其设置为.left.right.top.bottom。如果您愿意,您也可以在几秒钟内传递自定义持续时间:

ModalService.present(modalViewController, presenter: presentingViewController, enterFrom: .left, duration: 0.5)

ModalService.dismiss(self, exitTo: .left, duration: 2.0)

向@jcdmb点头,就这个问题构成了该课程解决方案内核的Objective C答案。

这是完整的课程。私有transitionSubtype返回的值看起来很奇怪但是故意这样设置。在假设需要“纠正”之前,您应该测试观察到的行为。 :)

import UIKit

class ModalService {

    enum presentationDirection {
        case left
        case right
        case top
        case bottom
    }

    class func present(_ modalViewController: UIViewController,
                       presenter fromViewController: UIViewController,
                       enterFrom direction: presentationDirection = .right,
                       duration: CFTimeInterval = 0.3) {
        let transition = CATransition()
        transition.duration = duration
        transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        transition.type = kCATransitionMoveIn
        transition.subtype = ModalService.transitionSubtype(for: direction)
        let containerView: UIView? = fromViewController.view.window
        containerView?.layer.add(transition, forKey: nil)
        fromViewController.present(modalViewController, animated: false)
    }

    class func dismiss(_ modalViewController: UIViewController,
                       exitTo direction: presentationDirection = .right,
                       duration: CFTimeInterval = 0.3) {
        let transition = CATransition()
        transition.duration = duration
        transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        transition.type = kCATransitionReveal
        transition.subtype = ModalService.transitionSubtype(for: direction, forExit: true)
        if let layer = modalViewController.view?.window?.layer {
            layer.add(transition, forKey: nil)
        }
        modalViewController.dismiss(animated: false)
    }

    private class func transitionSubtype(for direction: presentationDirection, forExit: Bool = false) -> String {
        if (forExit == false) {
            switch direction {
            case .left:
                return kCATransitionFromLeft
            case .right:
                return kCATransitionFromRight
            case .top:
                return kCATransitionFromBottom
            case .bottom:
                return kCATransitionFromTop
            }
        } else {
            switch direction {
            case .left:
                return kCATransitionFromRight
            case .right:
                return kCATransitionFromLeft
            case .top:
                return kCATransitionFromTop
            case .bottom:
                return kCATransitionFromBottom
            }
        }
    }
}