【问题标题】:Switch container view dynamically动态切换容器视图
【发布时间】:2013-04-17 05:03:50
【问题描述】:

我正在使用情节提要容器视图。所以我有一个包含容器视图的视图控制器。我在情节提要中有第二个较小的视图,它通过嵌入转场嵌入到该容器中。到目前为止一切顺利。

现在我希望能够在用户点击按钮时动态切换该容器视图的内容。该按钮将位于较大的主视图上。我制作了另一个尺寸相同的视图控制器,并为其赋予了不同的故事板 ID。

但是,我不知道如何编写开关代码。我只能为该容器创建一个嵌入 segue。

感谢您的任何帮助。

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    您需要使用自定义容器视图控制器 api 来进行控制器的切换。以下代码显示了一种方法。在这个项目中,我在主视图控制器(带有容器视图的那个)中有一个分段控件,可以在两个控制器之间切换。 initialVC 是嵌入在 IB 中的控制器,而替代VC 是我要切换到的控制器。属性 container 是容器视图的 IBOutlet。

    - (void)viewDidLoad {
        [super viewDidLoad];
        self.initialVC = self.childViewControllers.lastObject;
        self.substituteVC = [self.storyboard instantiateViewControllerWithIdentifier:@"Substitute"];
        self.currentVC = self.initialVC;
    }
    
    -(IBAction)switchControllers:(UISegmentedControl *)sender {
    
        switch (sender.selectedSegmentIndex) {
            case 0:
                if (self.currentVC == self.substituteVC) {
                    [self addChildViewController:self.initialVC];
                    self.initialVC.view.frame = self.container.bounds;
                    [self moveToNewController:self.initialVC];
                }
                break;
            case 1:
                if (self.currentVC == self.initialVC) {
                    [self addChildViewController:self.substituteVC];
                    self.substituteVC.view.frame = self.container.bounds;
                    [self moveToNewController:self.substituteVC];
                }
                break;
            default:
                break;
        }
    }
    
    
    -(void)moveToNewController:(UIViewController *) newController {
        [self.currentVC willMoveToParentViewController:nil];
        [self transitionFromViewController:self.currentVC toViewController:newController duration:.6 options:UIViewAnimationOptionTransitionFlipFromLeft animations:nil
                                completion:^(BOOL finished) {
                                    [self.currentVC removeFromParentViewController];
                                    [newController didMoveToParentViewController:self];
                                    self.currentVC = newController;
                                }];
    }
    

    编辑后:

    如果你想去没有动画的新控制器,你可以这样做(这代替了我在案例 1 下的代码)。

    [self addChildViewController:self.substituteVC];
    [self.substituteVC didMoveToParentViewController:self];
    self.substituteVC.view.frame = self.container.bounds;
    [self.container addSubview:self.substituteVC.view];
    [self.currentVC removeFromParentViewController];
    

    【讨论】:

    • 嘿,谢谢,太棒了。一件事 - 为了得到我想要的确切结果(直接交换 - 没有动画),我将你的 moveToNewController 方法更改为 duration:0 和 options:UIViewAnimationOptionTransitionNone。但是一些代码,包括完成块结构,似乎是多余的。有没有更简单的方法来编写直接(非动画)交换的最终方法?
    • @JamesWhite,我已经编辑了我的答案以展示如何在没有动画的情况下做到这一点。
    • 这种切换对我来说非常有用,但是我将 UITableViews 切换进和切换出容器视图,并且换入的表格视图不遵守“自动调整滚动视图插入”,导致前几个换入的 VC 中的项目出现在 iOS 7 标题栏下方。
    • 好的,我已经手动 self.substituteVC.tableView.contentInset = self.currentVC.tableView.contentInset 了。
    • @ronnyandre,您应该发布一个问题,然后说明您正在使用什么代码,以及您看到什么结果。
    【解决方案2】:

    rdelmar's answer 转换为 Swift 语法

        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.initialVC = self.childViewControllers.last
            self.substituteVC = self.storyboard!.instantiateViewControllerWithIdentifier("Substitute")
            self.currentVC = self.initialVC;
    
    }
        @IBAction func switchControllers(sender: UISegmentedControl) {
            switch sender.selectedSegmentIndex{
                case 0:
                    if (self.currentVC == self.substituteVC) {
                        self.addChildViewController(self.initialVC)
                        //self.initialVC.view.frame = self.containerView.bounds
                        moveToNewController(self.initialVC)
                    }
                case 1:
                    if (self.currentVC == self.initialVC) {
                        self.addChildViewController(self.substituteVC)
                        //self.substituteVC.view.frame = self.containerView.bounds
                        moveToNewController(self.substituteVC)
                    }
                default:
                break;
            }
        }
    
        func moveToNewController(newController : UIViewController){
            self.currentVC.willMoveToParentViewController(nil)
            self.transitionFromViewController(
                self.currentVC!,
                toViewController: newController,
                duration: 0.2,
                options: UIViewAnimationOptions.TransitionCrossDissolve,
                animations: nil,
                completion: { finished in
                    self.currentVC.removeFromParentViewController()
                    newController.didMoveToParentViewController(self)
                    self.currentVC = newController
            })
    
        }
    

    【讨论】:

      【解决方案3】:

      如果您处理超过 2 个子视图控制器,最好将它们存储在数组中。此外,每次将新子视图添加到容器视图时,都需要应用约束。这是已接受答案的修改版本(使用 Swift 2 语法):

      import UIKit
      
      class FooBarViewController: UIViewController
      {
          // MARK: - IBOutlets
      
          @IBOutlet weak var containerView: UIView!
      
          // MARK: - Properties
      
          var vcs = [UIViewController]()
          var currentVC: UIViewController!
      
          // MARK: - ViewController Lifecycle
      
          override func viewDidLoad()
          {
              super.viewDidLoad()
      
              vcs.append(childViewControllers.last!)
              vcs.append(storyboard!.instantiateViewControllerWithIdentifier("FooViewControler"))       
              vcs.append(storyboard!.instantiateViewControllerWithIdentifier("BarViewController"))
              currentVC = vcs[0]
      
              for vc in vcs {
                  vc.view.frame = containerView.bounds
              }
          }
      
          // MARK: - Methods
      
          func switchToViewController(targetVC: UIViewController)
          {
              addChildViewController(targetVC)
              currentVC.willMoveToParentViewController(nil)
      
              transitionFromViewController(
                  currentVC,
                  toViewController: targetVC,
                  duration: 0.0, // 0.3
                  options: .TransitionNone, // .TransitionCrossDissolve,
                  animations: nil,
                  completion: { finished in
                      self.currentVC.removeFromParentViewController()
                      targetVC.didMoveToParentViewController(self)
                      self.currentVC = targetVC
                      self.applyConstraints()
              })
          }
      
          func applyConstraints()
          {
              let viewsDict = ["newSubview": currentVC.view]
      
              currentVC.view.translatesAutoresizingMaskIntoConstraints = false
      
              containerView.addConstraints(
                  NSLayoutConstraint.constraintsWithVisualFormat("H:|[newSubview]|",
                      options: NSLayoutFormatOptions(rawValue: 0),
                      metrics: nil,
                      views: viewsDict))
      
              containerView.addConstraints(
                  NSLayoutConstraint.constraintsWithVisualFormat("V:|[newSubview]|",
                      options: NSLayoutFormatOptions(rawValue: 0),
                      metrics: nil, views:
                      viewsDict))
          }
      
          // MARK: - IBActions
      
          @IBAction func switchControllers(sender: UISegmentedControl)
          {
              let i = sender.selectedSegmentIndex
      
              if currentVC != vcs[i] {
                  self.addChildViewController(vcs[i])
                  switchToViewController(vcs[i])
              }
          }
      }
      

      【讨论】:

      • 你在哪里添加视图控制器到“containerView”?
      猜你喜欢
      • 1970-01-01
      • 2015-04-20
      • 2018-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多