【问题标题】:How to hide & unhide Master View Controller in SplitView Controller如何在 SplitView 控制器中隐藏和取消隐藏主视图控制器
【发布时间】:2011-11-05 13:02:05
【问题描述】:

我在 XCode 4.2 中创建了一个新的基于拆分视图的项目

然后在DetailViewController.m 文件中我添加了这个方法

- (BOOL)splitViewController: (UISplitViewController*)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation 
{
  //This method is only available in iOS5  

   return NO;
}

现在通过这样做,我可以一次显示我的 splitview 控制器的左右部分。

现在我在DetailViewController 导航栏中添加了一个UIBarButtonItem,我希望通过它可以在纵向和横向模式下隐藏和显示我的主视图。

- (IBAction)hideUnhide:(id)sender 
{

//How can hide & unhide

}

我该怎么做?

【问题讨论】:

    标签: iphone ipad ios5 customization uisplitviewcontroller


    【解决方案1】:
    instead spv.delegate=nil; spv.delegate=self;
    

    接下来你需要做的:

    [spv willRotateToInterfaceOrientation:self.interfaceOrientation duration:0];
    

    【讨论】:

    • 哈!我一直在到处寻找解决方案。不错的工作! PS - 爱飞出个未来。
    • spv.delegate=nil; spv.delegate=self -> 工作 -- [spv willRotateToInterfaceOrientation:self.interfaceOrientation duration:0] -> 不工作
    • 适用于 iOS 6.0,而我还必须为细节面板中的一些自定义视图设置 contentMode = UIViewContentModeRedraw,否则它们无法正确调整大小。
    • 虽然还是别忘了打splitViewController.view.setNeedsLayout,只是打willRotateToInterfaceOrientation好像还不够
    • 在iOS 7中,你不需要将delegate设置为nil然后设置为self,只需调用[self.splitViewController willRotateToInterfaceOrientation:self.interfaceOrientation duration:0];然后在下一行[self.splitViewController.view setNeedsLayout];,触发show/隐藏主视图控制器。
    【解决方案2】:

    'setNeedsLayout' 让 UISplitViewController 请求“shouldHideViewController”

    - (IBAction)hideUnhide:(id)sender  {
        UISplitViewController* spv = ...;
    
        self.hideMaster= !self.hideMaster;
        [ spv.view setNeedsLayout ]
    }
    

    【讨论】:

    • 我一直在寻找一种方法来让拆分视图问这个问题。不知道为什么我没有想到。谢谢!
    • SplitViewController (SVC) 在委托上使用 shouldHideViewController 的方式似乎在 5.1 中发生了变化。现在,当您设置委托时,SVC 将使用所有可能的方向调用 shouldHideViewController 一次(并且它不会再这样做)。因此,如果您想“通知” shouldHideViewController“改变主意”,仅在 SVC.view 上使用 setNeedsLayout 是不够的。您必须更改 SVC 上的委托值。注意:将委托“重新分配”给自己是不够的。似乎 SVC 检查委托是否实际上与当前分配的不同。
    • 我正在更改代理,但这还不足以让视图隐藏或显示主人。在我的应用程序中,我有一个始终隐藏主视图的视图,但是当弹出到该视图时,主视图仍然显示,即使它是委托。一旦我旋转,它按计划工作。但是 viewWillAppear 中的 setNeedsLayout 已经解决了这个问题。
    • 您好安德烈,感谢您的回复。但最近我创建了一个基于 splitview 的示例项目(XCode 4.3.2 和 iOS 5.1)并按照此处提到的方式进行操作,但仅在两个方向都正确显示左侧根视图控制器。但是当我创建一个我的详细视图控制器中的按钮并调用 hideUnhide:没有发生任何事情。左侧根视图控制器的隐藏和取消隐藏没有发生。
    【解决方案3】:

    在 iOS 5.1 中,您必须这样做:

    内部DetailViewController.m

    - (IBAction)hideUnhide:(id)sender  {
        UISplitViewController* spv = ...;
    
        self.hideMaster= !self.hideMaster;
    
        [spv.view setNeedsLayout];
        spv.delegate = nil;
        spv.delegate = self;
    }
    
    - (BOOL)splitViewController:(UISplitViewController*)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation {
        return self.hideMaster;
    }
    

    【讨论】:

    • 嗨曼尼,感谢您的回复。但是最近我创建了一个基于 splitview 的示例项目(XCode 4.3.2 和 iOS 5.1)并按照此处提到的方式进行操作,但仅在两个方向都正确显示左侧根视图控制器。但是当我创建一个我的详细视图控制器中的按钮并调用 hideUnhide:没有发生任何事情。左侧根视图控制器的隐藏和取消隐藏没有发生。
    【解决方案4】:

    我结合了上述响应,以下在 IOS 6 中运行良好:

    // In split delegate
    -(void)hideMaster:(BOOL)hideState
    {
       _masterIsHidden = hideState;
    
       [self.splitViewController.view setNeedsLayout];
       self.splitViewController.delegate = nil;
       self.splitViewController.delegate = self;
    
       [self.splitViewController willRotateToInterfaceOrientation:[UIApplication    sharedApplication].statusBarOrientation duration:0];
    }
    
    -(BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
    {
        return self.masterIsHidden;
    }
    

    【讨论】:

      【解决方案5】:
      -(IBAction)clickToShowMaster:(id)sender
      {
       UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"prev.png"] style:UIBarButtonItemStylePlain target:self action:@selector(clickToHidemaster:)];
       self.navigationItem.leftBarButtonItem = systemItem1;
      [self.tabBarController.tabBar setHidden:NO];
      [self hideMaster:NO];
      }
      -(void)hideMaster:(BOOL)hideState
      {
      
      ishideMaster=hideState;
      [self.splitViewController.view setNeedsLayout];
      self.splitViewController.delegate = nil;
      self.splitViewController.delegate = self;
      
      [self.splitViewController willRotateToInterfaceOrientation:[UIApplication    sharedApplication].statusBarOrientation duration:0];
      
       }
      
      -(void)hideMaster:(BOOL)hideState
      {
      ishideMaster=hideState;
      [self.splitViewController.view setNeedsLayout];
      self.splitViewController.delegate = nil;
      self.splitViewController.delegate = self;
      
      [self.splitViewController willRotateToInterfaceOrientation:[UIApplication    sharedApplication].statusBarOrientation duration:0];
      
      }
      
      
          #pragma mark - Split view
      
      -(BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
      {
      
          if(UIInterfaceOrientationIsPortrait(orientation))
          {
              UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"down.png"] style:UIBarButtonItemStylePlain target:self action:@selector(showPopup)];
              self.navigationItem.leftBarButtonItem = systemItem1;
              [self setUIforPortrait];
              return YES;
          }
           if (UIInterfaceOrientationIsLandscape(orientation))
          {
              if(ishideMaster==TRUE)
              {
                  UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"next.png"] style:UIBarButtonItemStylePlain target:self action:@selector(clickToShowMaster:)];
                  self.navigationItem.leftBarButtonItem = systemItem1;
                  [self setUIForFullLandscape];
              }
              else
              {
                  UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"prev.png"] style:UIBarButtonItemStylePlain target:self action:@selector(clickToHidemaster:)];
                  self.navigationItem.leftBarButtonItem = systemItem1;
                  [self setUIForHalfLandscape];
              }
              return ishideMaster;
          }
      
      }
      //add the navigation button on left top, to pop-up master view.
      - (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
      {
          [barButtonItem setImage:[UIImage imageNamed:@"down.png"]];
      
          UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"down.png"] style:UIBarButtonItemStylePlain target:self action:@selector(showPopup)];
          self.navigationItem.leftBarButtonItem = systemItem1;
         self.masterPopoverController = popoverController;
          self.masterPopoverController.delegate=self;
      }
      
      - (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
      {
          // Called when the view is shown again in the split view, invalidating the button and popover controller.
          //;
          if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
          {
              if(ishideMaster==FALSE)
              {
                  UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"prev.png"] style:UIBarButtonItemStylePlain target:self action:@selector(clickToHidemaster:)];
                  self.navigationItem.leftBarButtonItem = systemItem1;
              }
              else
              {
                  UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"next.png"] style:UIBarButtonItemStylePlain target:self action:@selector(clickToShowMaster:)];
                  self.navigationItem.leftBarButtonItem = systemItem1;
      
              }
          }
          else if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation))
          {
              [self.navigationItem setLeftBarButtonItem:nil animated:YES];
      
          }
         //self.masterPopoverController = nil;
      }
      

      【讨论】:

        【解决方案6】:

        在 iOS8 中这很容易。

        隐藏它

        [UIView animateWithDuration:0.2 animations:^{
            splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;
        } completion:nil];
        

        展示它

        [UIView animateWithDuration:0.2 animations:^{
            self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryOverlay;
        } completion:nil];
        

        【讨论】:

          【解决方案7】:

          关于 wzbozon 关于不需要重新分配委托的评论,我发现这两行

          self.splitViewController.delegate = nil;
          
          self.splitViewController.delegate = self;
          

          ...在模拟器上不需要,但在我的 iOS5 iPad 1 上需要。没有它们,隐藏/显示行为不会发生(单击按钮不会折叠主视图)。

          【讨论】:

            【解决方案8】:

            嗯,你的问题最简单的部分是使用布尔值,比如属性 hideMaster,然后

            - (IBAction)hideUnhide:(id)sender 
            {
            
               self.hideMaster= !self.hideMaster;
            
            }
            

            然后……

            - (BOOL)splitViewController: (UISplitViewController*)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation 
            {
              //This method is only available in iOS5  
            
               return self.hideMaster;
            }
            

            这很好用,但是 shouldHideViewController 仅在 splitVC 重绘期间被调用,例如在旋转期间,因此主控器只会隐藏/取消隐藏。

            【讨论】:

            • 我创建了一个测试项目(使用 Xcode 的“master Detail”模板),然后将这两个例程添加到 DetailVC.m,添加属性 hideMaster,并添加 UIBarButton 到详细信息栏,并链接hideUnhide。在模拟器中运行,Master 出现/消失并带有按钮。不会立即隐藏/取消隐藏 master,而是在下一次旋转时,所以它不是一个完整的解决方案。
            【解决方案9】:

            您可以通过触发UISplitViewControllerdisplayModeButtonItem 属性的动作来显示/隐藏主视图控制器:

            斯威夫特

            if let displayModeButtonItem = splitViewController?.displayModeButtonItem() {
                displayModeButtonItem.target?.performSelector(displayModeButtonItem.action)
            }
            

            目标-C

            UIBarButtonItem *displayModeButtonItem = [self.splitViewController displayModeButtonItem];
            [displayModeButtonItem.target performSelector: displayModeButtonItem.action];
            

            我觉得这比同时干涉代表、方向和布局更合适。

            【讨论】:

              【解决方案10】:

              SWIFT 3.0

              我用过

              override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
                      if segue.identifier == "showDetail" {
                          if let indexPath = self.tableView.indexPathForSelectedRow {
                              let object = self.exercises[indexPath.row] 
                              let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController
                              controller.detailItem = object
                              controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem
                              controller.navigationItem.leftItemsSupplementBackButton = true
                              UIView.animate(withDuration: 0.2, delay: 0.0, options: [.curveEaseOut], animations: {
                                  self.splitViewController?.preferredDisplayMode = .primaryHidden
                              }, completion: nil)
              
                          }
                      }
                  }
              

              【讨论】:

                【解决方案11】:
                - (BOOL)splitViewController:(UISplitViewController*)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation {
                    [spv.view setNeedsLayout];  //add the line
                    return self.hideMaster;
                }
                

                【讨论】:

                • 如果我这样做,应用程序将无法启动。有些人在应用启动后立即设置 splitViewControllerDelegate,所以我不建议这样做。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2013-04-27
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-04-10
                相关资源
                最近更新 更多