Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 使用UINavigationController从右向左推ViewController_Iphone_Objective C_Uinavigationcontroller - Fatal编程技术网

Iphone 使用UINavigationController从右向左推ViewController

Iphone 使用UINavigationController从右向左推ViewController,iphone,objective-c,uinavigationcontroller,Iphone,Objective C,Uinavigationcontroller,众所周知,UINavigationController从左到右推送视图控制器,有没有办法从右到左推送视图?喜欢后退按钮的动画。 现在我有这个: [self.navigationController pushViewController:viewController animated:YES]; 否,从右向左保留用于从导航堆栈弹出ViewController。但是,您可以通过自己设置视图动画来获得这种效果。比如: [UIView beginAnimations:@"rightToLeft" c

众所周知,UINavigationController从左到右推送视图控制器,有没有办法从右到左推送视图?喜欢后退按钮的动画。
现在我有这个:


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

否,从右向左保留用于从导航堆栈弹出ViewController。但是,您可以通过自己设置视图动画来获得这种效果。比如:

[UIView beginAnimations:@"rightToLeft" context:NULL];
CGRect newFrame = aView.frame;
newFrame.origin.x -= newFrame.size.width;
aView.frame = newFrame;
[UIView commitAnimations];
但是,这不会对导航控制器产生任何影响。

您似乎想“弹回”。这可以通过以下三种方法在UINavigationController实例上实现:

要返回到“根”控制器,请执行以下操作:

-(NSArray*)PoptorootViewController动画:(BOOL)动画

或返回到以前的一个控制器:

-(NSArray*)popToViewController:(UIViewController*)viewController动画:(BOOL)动画

或返回到先前按下的控制器:


-(UIViewController*)popViewControllerAnimated:(BOOL)animated

您可以从导航控制器的viewcontrollers数组创建一个NSMutableArray,并在当前viewController之前插入新的viewController。然后设置不带动画的ViewController阵列并弹出

UIViewController *newVC = ...;
NSMutableArray *vcs =  [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
[vcs insertObject:newVC atIndex:[vcs count]-1];
[self.navigationController setViewControllers:vcs animated:NO];
[self.navigationController popViewControllerAnimated:YES];
请试试这个

HomePageController  *pageView = [[HomePageController alloc] initWithNibName:@"HomePageController_iPhone" bundle:nil];

CATransition *transition = [CATransition animation];
transition.duration = 0.45;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
transition.delegate = self;
[self.navigationController.view.layer addAnimation:transition forKey:nil];

self.navigationController.navigationBarHidden = NO;
[self.navigationController pushViewController:pageView animated:NO];

此代码运行良好。请试一试

CATransition *transition = [CATransition animation];
transition.duration = 0.3f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionReveal;
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[self.navigationController pushViewController:phoneServicesViewController animated:NO];

我也有同样的问题,我就是这样解决的

[self.navigationController popViewControllerAnimated:YES];

这将类似于“返回”,即单击“返回”按钮并导航到上一页的情况

我认为这只是对最佳答案的改进:

UIViewController *newVC = ...;
[self.navigationController setViewControllers:@[newVC, self] animated:NO];
[self.navigationController popViewControllerAnimated:YES];

要返回到初始控制器,只需按一下即可。

根据@felixlam的回答,我升级并创建了一个“反向”方向导航控制器,该控制器覆盖了默认的按/按方法,从而实现如下操作

class LeftPushNavigationController: BaseNavigationController {

  override func viewDidLoad() {
    super.viewDidLoad()
    interactivePopGestureRecognizer?.isEnabled = false
  }

  override func pushViewController(_ viewController: UIViewController, animated: Bool) {
    // If the push is not animated, simply pass to parent
    guard animated else { return super.pushViewController(viewController, animated: animated) }

    // Setup back button
    do {
      // Hide original back button
      viewController.navigationItem.setHidesBackButton(true, animated: false)
      // Add new one
      viewController.navigationItem.rightBarButtonItem = UIBarButtonItem(
        image: #imageLiteral(resourceName: "iconBackReverse"),
        style: .plain,
        target: self,
        action: #selector(self.pop)
      )
    }

    // Calculate final order
    let finalVCs = self.viewControllers + [viewController]

    // Insert the viewController to the before-last position (so it can be popped to)
    var viewControllers = self.viewControllers
    viewControllers.insert(viewController, at: viewControllers.count - 1)

    // Insert viewcontroller before the last one without animation
    super.setViewControllers(viewControllers, animated: false)
    // Pop with the animation
    super.popViewController(animated: animated)
    // Set the right order without animation
    super.setViewControllers(finalVCs, animated: false)
  }

  override func popViewController(animated: Bool) -> UIViewController? {
    // If the push is not animated, simply pass to parent
    guard animated else { return super.popViewController(animated: animated) }

    guard self.viewControllers.count > 1 else { return nil }

    // Calculate final order
    var finalVCs = self.viewControllers
    let viewController = finalVCs.removeLast()

    // Remove the parent ViewController (so it can be pushed)
    var viewControllers = self.viewControllers
    let parentVC = viewControllers.remove(at: viewControllers.count - 2)

    // Set the viewcontrollers without the parent & without animation
    super.setViewControllers(viewControllers, animated: false)
    // Create push animation with the parent
    super.pushViewController(parentVC, animated: animated)
    // Set the right final order without animation
    super.setViewControllers(finalVCs, animated: false)

    // Return removed viewController
    return viewController
  }

  @objc
  private func pop() {
    _ = popViewController(animated: true)
  }

}

Swift 5.0

 let pageView = TaskFolderListViewController.init(nibName: "HomePageController_iPhone", bundle: nil)
 let transition = CATransition()
 transition.duration = 0.45
 transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.default)
 transition.type = CATransitionType.push
 transition.subtype = CATransitionSubtype.fromLeft
 self.navigationController?.view.layer.add(transition, forKey: kCATransition)
 self.navigationController?.pushViewController(pageView, animated: false)

根据前面的最佳答案,您可以进行
UINavigationController
扩展,并保留导航堆栈,如下所示:

extension UINavigationController {
    /// Pushes view controller into navigation stack with backwards animation.
    func pushBackwards(viewController newViewController: UIViewController) {
        if let currentController = viewControllers.last {
            let previousControllers = viewControllers[0..<viewControllers.endIndex-1]
            var controllers = Array(previousControllers + [newViewController, currentController])
            setViewControllers(controllers, animated: false)
            popViewController(animated: true)
            // Adjusting the navigation stack
            _ = controllers.popLast()
            controllers.insert(currentController, at: controllers.count-1)
            setViewControllers(controllers, animated: false)
        } else {
            // If there is no root view controller, set current one without animation.
            setViewControllers([newViewController], animated: false)
        }
    }
}

扩展UINavigationController{ ///使用向后动画将视图控制器推入导航堆栈。 func向后推(视图控制器newViewController:UIViewController){ 如果让currentController=viewControllers.last{
让previousControllers=viewControllers[0..很高兴知道,如果我从导航堆栈弹出视图,该怎么做?@Ludo:您不能从导航堆栈弹出视图。“堆栈”包含viewcontrollers抱歉,我的不好。我键入了视图,但当然有viewcontrollers。如何弹出viewcontrollers由其他答案解释。有趣的方法。可能会起作用,但可能会附带一些标题。听起来有点有趣。我需要在viewcontroller中传递一些信息,以便它可能会起作用通过这种方式。你能告诉我如何在当前ViewController之前插入我的新ViewController吗?我添加了一个代码段,说明了这种方法。这肯定不符合HIG,可能会让用户感到困惑。但它应该按照你的要求做。不过我没有测试。我创建了一个基于n这个想法:太黑了。使用CATTransition应该是正确的方法。谢谢你的帮助,我只想尝试Felix的答案,但我真的不知道怎么做。为什么你要设置两次转换的类型?类型应该是kCatransionPush,子类型是kCatransionFromLeft。设置两次类型是多余的。最后我会编辑答案!“我已经试了几个小时了,直到你的都没成功。@特里安纳布兰农很高兴听到代码片段对你有帮助。谢谢你,聪明的解决方案
extension UINavigationController {
    /// Pushes view controller into navigation stack with backwards animation.
    func pushBackwards(viewController newViewController: UIViewController) {
        if let currentController = viewControllers.last {
            let previousControllers = viewControllers[0..<viewControllers.endIndex-1]
            var controllers = Array(previousControllers + [newViewController, currentController])
            setViewControllers(controllers, animated: false)
            popViewController(animated: true)
            // Adjusting the navigation stack
            _ = controllers.popLast()
            controllers.insert(currentController, at: controllers.count-1)
            setViewControllers(controllers, animated: false)
        } else {
            // If there is no root view controller, set current one without animation.
            setViewControllers([newViewController], animated: false)
        }
    }
}