Подтвердить что ты не робот

Анимация presentModalViewController справа/слева

В настоящее время я использую [self presentModalViewController :newVC animated:YES]. Я хочу представить newViewcontroller слева/справа/сверху/снизу с помощью push-эффекта. Я попытался использовать CATransition, но он отображает черный экран между переходами.

4b9b3361

Ответ 1

При наличии:

CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[self.view.window.layer addAnimation:transition forKey:nil];

[self presentModalViewController:viewCtrl animated:NO];

При увольнении:

CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[self.view.window.layer addAnimation:transition forKey:nil];
[self dismissModalViewControllerAnimated:NO];

Ответ 2

У меня была та же проблема. Предположим, вы хотите представить контроллер 2 просмотра из контроллера 1. В первом контроллере представления используйте

 [self presentModalViewController: controller animated: NO]];

Во втором контроллере представления в viewWillAppear: метод добавляет код

    CATransition *animation = [CATransition animation];

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

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


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

Все будет хорошо. Если черный экран снова появляется, если вы используете навигационный контроллер, замените

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

с

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

Ответ 3

Есть только четыре UIModalTransitionStyles:

UIModalTransitionStyleCoverVertical
UIModalTransitionStyleFlipHorizontal
UIModalTransitionStyleCrossDissolve
UIModalTransitionStylePartialCurl

Например:

UIViewController *controller = [[[MyViewController alloc] init] autorelease];
UIModalTransitionStyle trans = UIModalTransitionStyleFlipHorizontal;
[UIView beginAnimations: nil context: nil];
[UIView setAnimationTransition: trans forView: [self window] cache: YES];
[navController presentModalViewController: controller animated: NO];
[UIView commitAnimations];

Ответ 4

После X >= 4 часа работы это работает без "разрыва" или других артефактов фона:

class AboutTransition: NSObject, UIViewControllerAnimatedTransitioning {

    let presenting: Bool
    let duration: NSTimeInterval

    init(presenting: Bool, duration: NSTimeInterval = 0.25) {
        self.presenting = presenting
        self.duration = duration
    }

    @objc func transitionDuration(ctx: UIViewControllerContextTransitioning) -> NSTimeInterval {
        return duration
    }

    @objc func animateTransition(ctx: UIViewControllerContextTransitioning) {
        let duration = transitionDuration(ctx)
        let containerView = ctx.containerView()
        let fromViewController = ctx.viewControllerForKey(UITransitionContextFromViewControllerKey)!
        let toViewController = ctx.viewControllerForKey(UITransitionContextToViewControllerKey)!
        let fromView = fromViewController.view // 7.0 & 8.0 compatible vs. viewForKey:
        let toView = toViewController.view     // 7.0 & 8.0 compatible vs. viewForKey:

        containerView.addSubview(fromView)
        containerView.addSubview(toView)

        let offScreenRight = CGAffineTransformMakeTranslation(containerView.frame.width, 0)
        let offScreenLeft = CGAffineTransformMakeTranslation(-containerView.frame.width, 0)

        fromView.transform = CGAffineTransformIdentity
        toView.transform = self.presenting ? offScreenRight : offScreenLeft

        UIView.animateWithDuration(duration, delay:0, options:UIViewAnimationOptions(0), animations: {
            fromView.transform = self.presenting ? offScreenLeft : offScreenRight
            toView.transform = CGAffineTransformIdentity

        }, completion: { (finished: Bool) in
            ctx.completeTransition(finished)
            if finished {
                fromView.removeFromSuperview()
                fromView.frame = toView.frame // reset the frame for reuse, otherwise frame transforms will accumulate
            }
        })
    }
}

Тогда в AppDelegate.swift:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UINavigationControllerDelegate {

    lazy var window: UIWindow? = {
        return UIWindow(frame: UIScreen.mainScreen().bounds)
    }()

    lazy var storyboard = UIStoryboard(name: "Main", bundle: nil)

    lazy var nav: UINavigationController = {
        var r = self.storyboard.instantiateInitialViewController() as! UINavigationController
        r.delegate = self
        return r
    }()

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        self.window!.rootViewController = nav
        self.window!.makeKeyAndVisible()

        // .. other setup

        return true
    }

    // ...


    // MARK: - UINavigationControllerDelegate

    func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        // Example of a SettingsViewController which pushes AboutViewController
        if fromVC is SettingsViewController && toVC is AboutViewController { // Push to About
            return AboutTransition(presenting: true)
        } else if fromVC is AboutViewController && toVC is SettingsViewController { // Pop to Settings
            return AboutTransition(presenting: false)
        }
        return nil
    }
}

Предполагается, что приложение использует раскадровку по умолчанию с исходным VC как UINavigationController

Ответ 5

Вы можете установить transitioningDelegate на контроллер представления, который вы хотите представить. Вы должны соответствовать протоколам UIViewControllerTransitioningDelegate и UIViewControllerAnimatedTransitioning. И, реализуя animateTransition(transitionContext: UIViewControllerContextTransitioning), вы можете анимировать подчиненные представления или контроллеры.

Функция, выполняющая переход

class fromViewController : UIViewController {
    let transitionManager = TransitionManager()

    func transitionToViewController() {
      toController.transitioningDelegate = transitionManager
      presentViewController(toController, animated: true, completion: nil)
    }
}

Затем TransitionManager выглядит так:

import UIKit

class TransitionManager : UIPercentDrivenInteractiveTransition {
    var presenting = false
}

// MARK: UIViewControllerAnimatedTransitioning
extension TransitionManager : UIViewControllerAnimatedTransitioning {
    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
        let container = transitionContext.containerView()
        let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)!
        let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!

        let offScreenRight = CGAffineTransformMakeTranslation(container.frame.width, 0)
        let offScreenLeft = CGAffineTransformMakeTranslation(-container.frame.width, 0)

        toView.transform = self.presenting ? offScreenRight : offScreenLeft

        container.addSubview(toView)
        container.addSubview(fromView)
        let duration = self.transitionDuration(transitionContext)

        UIView.animateWithDuration(duration, delay: 0.0, usingSpringWithDamping: 1, initialSpringVelocity: 0.8, options: nil, animations: {
          fromView.transform = self.presenting ? offScreenLeft : offScreenRight
          toView.transform = CGAffineTransformIdentity

          }, completion: { finished in
            transitionContext.completeTransition(true)
        })
    }


    func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
        return 0.3
    }
}


// MARK: UIViewControllerTransitioningDelegate
extension TransitionManager : UIViewControllerTransitioningDelegate {
    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        self.presenting = true
        return self
    }

    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        self.presenting = false
        return self
    }
}