我有一个基于导航的应用程序,我想改变推送和弹出动画的动画。我该怎么做呢?
编辑2018
这个问题有很多答案,现在已经有很长一段时间了,我重新选择了我认为最相关的答案。如果有人有不同的想法,请在评论中告诉我
我有一个基于导航的应用程序,我想改变推送和弹出动画的动画。我该怎么做呢?
编辑2018
这个问题有很多答案,现在已经有很长一段时间了,我重新选择了我认为最相关的答案。如果有人有不同的想法,请在评论中告诉我
当前回答
使用私人通话是一个坏主意,因为苹果不再批准这样做的应用程序。 也许你可以试试这个:
//Init Animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration: 0.50];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.navigationController.view cache:YES];
//Create ViewController
MyViewController *myVC = [[MyViewController alloc] initWith...];
[self.navigationController pushViewController:myVC animated:NO];
[myVC release];
//Start Animation
[UIView commitAnimations];
其他回答
非常简单
self.navigationController?.view.semanticContentAttribute = .forceRightToLeft
我知道这个帖子很旧了,但我想我应该发表我的意见。你不需要制作一个自定义动画,有一个简单(可能是hack)的方法来做它。不使用push,而是创建一个新的导航控制器,使新的视图控制器成为那个nav控制器的根视图控制器,然后从原始的nav控制器中呈现出nav控制器。现在是很容易自定义的许多风格,不需要做一个自定义动画。
例如:
UIViewcontroller viewControllerYouWantToPush = UIViewController()
UINavigationController newNavController = UINavigationController(root: viewControllerYouWantToView)
newNavController.navBarHidden = YES;
self.navigationController.present(newNavController)
你可以随心所欲地改变演示风格。
意识到这是一个老问题。我仍然想张贴这个答案,因为我有一些问题弹出几个viewcontroller与建议的答案。我的解决方案是子类UINavigationController和覆盖所有的弹出和推方法。
翻转导航控制器.h
@interface FlippingNavigationController : UINavigationController
@end
FlippingNavigationController.m:
#import "FlippingNavigationController.h"
#define FLIP_DURATION 0.5
@implementation FlippingNavigationController
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[UIView transitionWithView:self.view
duration:animated?FLIP_DURATION:0
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionFlipFromRight
animations:^{ [super pushViewController:viewController
animated:NO]; }
completion:nil];
}
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
return [[self popToViewController:[self.viewControllers[self.viewControllers.count - 2]]
animated:animated] lastObject];
}
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated
{
return [self popToViewController:[self.viewControllers firstObject]
animated:animated];
}
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
{
__block NSArray* viewControllers = nil;
[UIView transitionWithView:self.view
duration:animated?FLIP_DURATION:0
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionFlipFromLeft
animations:^{ viewControllers = [super popToViewController:viewController animated:NO]; }
completion:nil];
return viewControllers;
}
@end
使用私人通话是一个坏主意,因为苹果不再批准这样做的应用程序。 也许你可以试试这个:
//Init Animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration: 0.50];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.navigationController.view cache:YES];
//Create ViewController
MyViewController *myVC = [[MyViewController alloc] initWith...];
[self.navigationController pushViewController:myVC animated:NO];
[myVC release];
//Start Animation
[UIView commitAnimations];
由于这是谷歌上的排名第一的结果,我想我要分享我认为是最理智的方式;也就是使用ios7 +过渡API。我用Swift 3在iOS 10上实现了这个功能。
如果你创建UINavigationController的子类并返回一个符合uiviewcontrolleranimatedtransioning协议的类的实例,那么将这个与UINavigationController如何在两个视图控制器之间动画结合起来是非常简单的。
例如,这是我的UINavigationController子类:
class NavigationController: UINavigationController {
init() {
super.init(nibName: nil, bundle: nil)
delegate = self
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension NavigationController: UINavigationControllerDelegate {
public func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return NavigationControllerAnimation(operation: operation)
}
}
你可以看到,我设置了UINavigationControllerDelegate本身,在我的子类的扩展中,我实现了UINavigationControllerDelegate中的方法,它允许你返回一个自定义动画控制器(即,NavigationControllerAnimation)。这个自定义动画控制器将取代库存动画为您。
您可能想知道为什么我通过NavigationControllerAnimation实例的初始化器将操作传递给它。我这样做是为了在NavigationControllerAnimation的uiviewcontrolleranimatedtransiating协议的实现中,我知道操作是什么(即“push”或“pop”)。这有助于知道我应该做什么样的动画。大多数情况下,您希望根据操作执行不同的动画。
其余的都是标准的。在uiviewcontrolleranimatedtransiating协议中实现两个必需的函数,并按你喜欢的方式进行动画:
class NavigationControllerAnimation: NSObject, UIViewControllerAnimatedTransitioning {
let operation: UINavigationControllerOperation
init(operation: UINavigationControllerOperation) {
self.operation = operation
super.init()
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else { return }
let containerView = transitionContext.containerView
if operation == .push {
// do your animation for push
} else if operation == .pop {
// do your animation for pop
}
}
}
重要的是要记住,对于每个不同类型的操作(例如,“push”或“pop”),to和from视图控制器将是不同的。当你在进行推送操作时,to视图控制器将是被推送的那个。当你在弹出操作中,to视图控制器将是被转换到的那个,而from视图控制器将是被弹出的那个。
另外,to视图控制器必须作为转换上下文中containerView的子视图添加。
当你的动画完成时,你必须调用transitionContext.completeTransition(true)。如果你正在做一个交互式转换,你将不得不动态返回一个Bool到completeTransition(didComplete: Bool),这取决于转换是否在动画结束时完成。
最后(可选阅读),您可能想看看我是如何完成我正在进行的转换的。这段代码有点粗糙,我写得很快,所以我不会说它是伟大的动画代码,但它仍然显示了如何做动画部分。
我的转变非常简单;我想模仿UINavigationController通常做的相同的动画,但不是“下一页上方”动画,我想在新视图控制器出现的同时实现旧视图控制器的1:1动画。这使得两个视图控制器看起来好像是固定在一起的。
对于push操作,首先需要在屏幕外的x轴上设置toViewController的视图原点,将其添加为containerView的子视图,通过设置该原点将其动画化到屏幕上。X到0。与此同时,我通过设置fromViewController的原点来使它动画化。X离开屏幕:
toViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.size.width, dy: 0.0)
containerView.addSubview(toViewController.view)
UIView.animate(withDuration: transitionDuration(using: transitionContext),
delay: 0,
options: [ UIViewAnimationOptions.curveEaseOut ],
animations: {
toViewController.view.frame = containerView.bounds
fromViewController.view.frame = containerView.bounds.offsetBy(dx: -containerView.frame.size.width, dy: 0)
},
completion: { (finished) in
transitionContext.completeTransition(true)
})
弹出操作基本上是相反的。添加toViewController作为containerView的子视图,并将fromViewController动画移到右边,就像你从左边动画toViewController一样:
containerView.addSubview(toViewController.view)
UIView.animate(withDuration: transitionDuration(using: transitionContext),
delay: 0,
options: [ UIViewAnimationOptions.curveEaseOut ],
animations: {
fromViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.width, dy: 0)
toViewController.view.frame = containerView.bounds
},
completion: { (finished) in
transitionContext.completeTransition(true)
})
以下是整个swift文件的要点:
https://gist.github.com/alanzeino/603293f9da5cd0b7f6b60dc20bc766be