简体   繁体   English

iOS 7改变了pushviewcontroller的动画方向

[英]iOS 7 change pushviewcontroller animation direction

When i push a viewcontroller the animation is always from right to left. 当我推动一个视图控制器时,动画总是从右到左。 I want to change that animation to the inverse left to right. 我想将该动画从左向右反转。 I have tried this code but doesnt work. 我尝试过这段代码但不起作用。 The animation is still from right to left. 动画仍然是从右到左。 How can i achive this simply and correctly? 我怎样才能简单而正确地实现这一目标? Need help please. 需要帮助。 Thanks in advance. 提前致谢。

//NOT WORKING
myViewController *mController = [self.storyboard instantiateViewControllerWithIdentifier:@"myViewController"];

CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;

[self.view.layer addAnimation:transition forKey:nil];

[self.navigationController pushViewController:mController animated:YES];

Since this question mentions iOS 7 I'm quite surprised the answer doesn't mention the Animated Transitions API introduced in iOS 7. 由于这个问题提到了iOS 7,我很惊讶答案没有提到iOS 7中引入的Animated Transitions API。

If you want to get straight into GitHub the objc.io guys have a great post with a linked project here 如果你想直接进入GitHub,objc.io的人在这里有一个很棒的帖子和链接项目

Take a look at the documentation and you will see the following: 看一下文档,您将看到以下内容:

@availability(iOS, introduced=7.0)
optional func navigationController(navigationController: UINavigationController, 
animationControllerForOperation operation: UINavigationControllerOperation, 
fromViewController fromVC: UIViewController,
 toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?

Or in Objective-C 或者在Objective-C中

- (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                   animationControllerForOperation:(UINavigationControllerOperation)operation
                                                fromViewController:(UIViewController *)fromVC
                                                  toViewController:(UIViewController *)toVC  NS_AVAILABLE_IOS(7_0);

What this means is that from iOS 7 you can control how the navigation controller implements its animations for pushes and pops. 这意味着从iOS 7开始,您可以控制导航控制器如何实现推送和弹出的动画。

All that is needed is for you to set the delegate of the navigation controller and vend the correct animator object when appropriate. 所需的只是您设置导航控制器的委托并在适当时提供正确的动画制作对象。 So lets get started: 让我们开始吧:

1. Set the UINavigationControllerDelegate 1.设置UINavigationControllerDelegate

I typically like to have an App-Wide Navigation Coordinator that manages all my transitions etc. So ideally you want some object that will be alive for the duration of the NavigationController. 我通常喜欢有一个应用程序范围的导航协调器来管理我的所有过渡等。所以理想情况下你想要一些在NavigationController持续时间内活着的对象。 So we might have a coordinator that looks like this: 所以我们可能会有一个看起来像这样的协调器:

class NavigationCoordinationController: NSObject {
    private(set) var navigationController:UINavigationController        

    required init(navigationController: UINavigationController) {
        self.navigationController = navigationController
        super.init()
        navigationController.delegate = self
    }
}

I typically create this in the App Delegate so it can be referenced anywhere. 我通常在App Delegate中创建它,以便可以在任何地方引用它。 You could also set the delegate on a per view controller basis, creating a custom UINavigationController subclass, or wherever you see fit. 您还可以基于每个视图控制器设置委托,创建自定义UINavigationController子类,或者您认为合适的位置。

2. Create A Custom Animator 2.创建自定义动画师

Now we need an object that conforms to the UIViewControllerAnimatedTransitioning protocol. 现在我们需要一个符合UIViewControllerAnimatedTransitioning协议的对象。 This object will be called upon to apply the animation whenever an animated transition is needed. 每当需要动画转换时,将调用此对象来应用动画。 This example is a simple animation that fades and expands the fromView in the transition so its relevant for a Push. 此示例是一个简单的动画,它在转换中淡化和扩展fromView,因此它与Push相关。

class CustomPushExpansionTransitioner: NSObject, UIViewControllerAnimatedTransitioning {
    func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
        return 1
    }

    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
        let fromView: UIView = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
        let toView: UIView = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
        let container = transitionContext.containerView()
        container.addSubview(toView)
        container.bringSubviewToFront(fromView)

        toView.frame = container.convertRect(fromView.bounds, fromView: fromView)

        UIView.animateWithDuration(transitionDuration(transitionContext),
            animations: { () -> Void in
                fromView.alpha = 0
                fromView.transform = CGAffineTransformConcat(fromView.transform, CGAffineTransformMakeScale(1.3, 1.3))
        }) { (complete) -> Void in
            transitionContext.completeTransition(true)
        }
    }
}

3. Vend The Animator Where Necessary 3.供应动画师必要的地方

Now we need to implement the UINavigationController delegate and vend our custom animator when needed. 现在我们需要实现UINavigationController委托并在需要时出售我们的自定义动画师。

extension NavigationCoordinationController: UINavigationControllerDelegate {
    func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        switch operation {
        case .Push:
            return LaunchToHomeTransitioner()
        case .Pop:
            break
        case .None:
            break
        }
        return nil
    }
}

And there you go, you now have total control over your UINavigationController transitions 你去了,你现在可以完全控制你的UINavigationController过渡

You are actually doing it right, but as far as I understand from your code, you are not overriding the method: 您实际上是正确的,但据我所知,从您的代码中,您没有覆盖该方法:

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated

So, you need to inherit from UINavigationController and override the above method. 因此,您需要继承UINavigationController并覆盖上述方法。

Here's how I do it (push + pop): 这是我的方式(推+弹出):

Push: 推:

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
    UIView *theWindow = self.view ;
    if( animated ) {
        CATransition *animation = [CATransition animation];
        [animation setDuration:0.45f];
        [animation setType:kCATransitionPush];
        [animation setSubtype:kCATransitionFromLeft];
        [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
        [[theWindow layer] addAnimation:animation forKey:@""];
    }

    //make sure we pass the super "animated:NO" or we will get both our
    //animation and the super's animation
    [super pushViewController:viewController animated:NO];

    [self swapButtonsForViewController:viewController];

}

Pop : 流行:

- (UIViewController *)popViewControllerAnimated:(BOOL)animated {
    UIView *theWindow = self.view ;
    if( animated ) {
        CATransition *animation = [CATransition animation];
        [animation setDuration:0.45f];
        [animation setType:kCATransitionPush];
        [animation setSubtype:kCATransitionFromRight];
        [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
        [[theWindow layer] addAnimation:animation forKey:@""];
    }
    return [super popViewControllerAnimated:NO];
}
NextViewController *next = [[NextViewController alloc] initWithNibName:@"NextViewController" bundle:nil];

[UIView transitionWithView:self.navigationController.view 
              duration:0.75 
               options:UIViewAnimationOptionTransitionFlipFromRight 
            animations:^{
             [self.navigationController pushViewController:next animated:NO];
            } 
            completion:nil];

Try Above code 试试上面的代码

You can try this as well. 你也可以试试这个。

CATransition *transition = [CATransition animation];

transition.duration = 0.5;
transition.type = kCATransitionMoveIn;
transition.subtype = kCATransitionFromLeft;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

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

DrawingResultsViewController *dr = [DrawingResultsViewController createAndShowProfile:YES];

[self.navigationController pushViewController:dr animated:YES];

If some one is looking for the same answer in Xamarin.iOS (based on gran33 answer) : 如果有人在Xamarin.iOS中寻找相同的答案(基于gran33答案):

public override void PushViewController(UIViewController viewController, bool animated)
{
    if (animated)
    {
        CATransition animation = new CATransition()
        {
            Duration = 0.5,
            Type = CAAnimation.TransitionPush,
            Subtype = CAAnimation.TransitionFromTop,
            TimingFunction = AMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut)
        };
        View.Layer.AddAnimation(animation, CALayer.Transition);

        base.PushViewController(viewController, false);
    }
}

public override UIViewController PopViewController(bool animated)
{
    if (animated)
    {
        CATransition animation = new CATransition()
        {
            Duration = 0.5,
            Type = CAAnimation.TransitionPush,
            Subtype = CAAnimation.TransitionFromBottom,
            TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut)
            };
            View.Layer.AddAnimation(animation, CALayer.Transition);

            return base.PopViewController(false);
        }
    return base.PopViewController(animated);
}

Assuming myViewController is your view controller, pass custom transition to the nav controller layer. 假设myViewController是您的视图控制器,请将自定义过渡传递到导航控制器层。

CATransition *transition = [CATransition animation];

transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;

[self.navigationController.view.layer addAnimation:transition forKey:@"pushViewController"]; 

[self.navigationController pushViewController:myViewController animated:NO];

For Swift 4.0+ 适用于Swift 4.0+

1 - Create a extension: 1 - 创建扩展程序:

extension UINavigationController {
    func customPopView(_ viewController: UIViewController) {
        let transition: CATransition = CATransition()
        transition.duration = 0.3
        transition.type = CATransitionType.push
        transition.subtype = CATransitionSubtype.fromLeft
        view.layer.add(transition, forKey: nil)
        pushViewController(viewController, animated: false)
    }
}

2 - Call: 2 - 致电:

self.navigationController?.customPopView(yourViewController)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM