当我推动一个视图控制器时,动画总是从右到左。我想将该动画从左向右反转。 我尝试过这段代码但不起作用。动画仍然是从右到左。我怎样才能简单而正确地实现这一目标?需要帮助。提前谢谢。
//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];
答案 0 :(得分:10)
由于这个问题提到了iOS 7,我很惊讶答案并未提及iOS 7中引入的Animated Transitions API。
如果你想直接进入GitHub,那么objc.io的人有一个很棒的帖子,链接项目here
查看文档,您将看到以下内容:
@availability(iOS, introduced=7.0)
optional func navigationController(navigationController: UINavigationController,
animationControllerForOperation operation: UINavigationControllerOperation,
fromViewController fromVC: UIViewController,
toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?
或在Objective-C
- (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0);
这意味着从iOS 7开始,您可以控制导航控制器如何实现推送和弹出动画。
您需要的只是设置导航控制器的委托并在适当时提供正确的动画制作对象。让我们开始吧:
我通常喜欢使用应用程序范围的导航协调器来管理我的所有转换等。理想情况下,您需要一些在NavigationController持续时间内处于活动状态的对象。所以我们可能会有一个看起来像这样的协调员:
class NavigationCoordinationController: NSObject {
private(set) var navigationController:UINavigationController
required init(navigationController: UINavigationController) {
self.navigationController = navigationController
super.init()
navigationController.delegate = self
}
}
我通常在App Delegate中创建它,以便可以在任何地方引用它。您还可以基于每个视图控制器设置委托,创建自定义UINavigationController子类,或者您认为合适的位置。
现在我们需要一个符合UIViewControllerAnimatedTransitioning
协议的对象。每当需要动画转换时,将调用此对象来应用动画。此示例是一个简单的动画,它在转换中淡化和扩展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)
}
}
}
现在我们需要实现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
}
}
你去了,你现在可以完全控制你的UINavigationController过渡
答案 1 :(得分:9)
你实际上是正确的,但据我所知,从你的代码中,你并没有覆盖这个方法:
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
因此,您需要继承UINavigationController
并覆盖上述方法。
以下是我的表现(推+弹出):
推送:
- (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];
}
答案 2 :(得分:4)
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];
尝试以上代码
答案 3 :(得分:2)
您也可以试试这个。
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];
答案 4 :(得分:0)
如果有人在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);
}
答案 5 :(得分:0)
假设myViewController
是您的视图控制器,
CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[self.navigationController.view.layer addAnimation:animation forKey:@"pushViewController"];
[self.navigationController pushViewController:myViewController animated:NO];
答案 6 :(得分:0)
对于 Swift 4.0 +
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-致电:
self.navigationController?.customPopView(yourViewController)