【问题标题】:Hiding UISplitViewController overlay in portrait以纵向隐藏 UISplitViewController 覆盖
【发布时间】:2014-08-28 20:56:47
【问题描述】:

在采用新的UISplitViewController 时,我试图更改使用UISplitViewControllerDisplayModeAutomatic 模式时发生的默认行为。

在纵向工作时,我希望在用户触发向细节侧的推送时隐藏主叠加层。默认情况下,叠加层会一直显示在屏幕上,直到用户点击详细信息侧。

我已尝试对委托使用以下内容:

- (BOOL)splitViewController:(UISplitViewController *)splitViewController showDetailViewController:(UIViewController *)vc sender:(id)sender
{
    if (splitViewController.displayMode == UISplitViewControllerDisplayModePrimaryOverlay) {
        [UIView animateWithDuration:0.3 animations:^{
            splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;
        }];
    }
    return NO;
}

这给了我想要的纵向行为,但这会破坏横向模式(我想表现得像 UISplitViewControllerDisplayModeAllVisible)。如果您完成了推动然后旋转设备,左侧仍然隐藏(如预期的那样)。我找不到合适的地方来重新设置旋转的首选模式以显示左侧(因为特征集合不能用于在 iPad 上区分横向与纵向)。

如何手动触发覆盖层的关闭?

重复说明: iOS8 已完全更改 UISplitViewController,因此 14 年 6 月之前的所有其他 SO 答案可能都是错误的(我已经挖掘了其中的许多, 以防万一)

【问题讨论】:

    标签: ios uisplitviewcontroller ios8 screen-rotation ios-universal-app


    【解决方案1】:

    我遇到了和你一样的问题。我在 Xamarin 的单声道触控平台上执行此操作,但我认为结果会是一样的。

    就像 LaborEtArs 所说的,将您的代码移动到主视图控制器的 prepareForSegue:sender: 方法中。然后在设置为隐藏后将模式设置为自动:

    if (splitViewController.displayMode == UISplitViewControllerDisplayModePrimaryOverlay) {
        splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;
        splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic;
    }
    

    这样做后,它不再打破横向模式。

    【讨论】:

      【解决方案2】:

      只需将您的代码(不带return NO;)放在主视图控制器prepareForSegue:sender:tableView:didSelectRowAtIndexPath: 方法中。 在那里它完美地工作!

      【讨论】:

      • 不错的简单答案。我发现 0.3 的持续时间与使用滑动或按钮切换时的动画相比有点慢; 0.2 秒似乎是正确的。
      • 这很好用,但是如果在设备旋转为横向时显示主视图,则详细视图不会适当地调整大小。
      【解决方案3】:

      除了LaborEtArs 建议在prepareForSegue:sender:tableView:didSelectRowAtIndexPath: 中制作动画外,如果您的应用程序通常将splitViewController:preferredDisplayMode 设置为UISplitViewControllerDisplayModeAutomatic,只需使用带有完成处理程序的animateWithDuration: 方法动画结束后恢复displayMode:

      - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
          if ([[segue identifier] isEqualToString:@"showDetail"]) {
      
              // configure the detail controller
      
              if (self.splitViewController.displayMode == UISplitViewControllerDisplayModePrimaryOverlay) {
                  [UIView animateWithDuration:0.3 animations:^{
                      self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;
                  } completion:^(BOOL finished){
                      self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic;
              }];
          }
      }
      

      【讨论】:

      • 动画对于实现这一点非常重要。荣誉。然而,将它放在didSelectRowAtIndexPath 中会导致一个奇怪的细节表视图动画(不受欢迎)。将它放在prepareForSegue:sender 中会产生出色的动画效果。
      【解决方案4】:

      这里是 Swift 版本:

      if (self.splitViewController?.displayMode == UISplitViewControllerDisplayMode.PrimaryOverlay){
          splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryHidden
          splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.Automatic
      } else {
          println(self.splitViewController?.displayMode)
      }
      

      放置在prepareForSegue中

      【讨论】:

        【解决方案5】:

        iOS 13 及更高版本

        此方法不在公共标头中,但您可以按如下方式添加:

        @interface UISplitViewController()
        - (void)toggleMasterVisible:(id)sender;
        @end
        

        iOS 13 之前

        我曾经使用这种方式,但在 iOS 13 的新 UISplitViewControllerPanelImpl 中不再适用:

        @interface AppDelegate ()
        #pragma clang diagnostic push
        #pragma clang diagnostic ignored "-Wdeprecated-declarations"
        @property (nonatomic, assign) UIPopoverController *splitPopoverController;
        #pragma clang diagnostic pop
        @end
        
        @implementation AppDelegate
        
        #pragma clang diagnostic push
        #pragma clang diagnostic ignored "-Wdeprecated-declarations"
        - (void)splitViewController:(UISplitViewController *)splitViewController popoverController:(UIPopoverController *)popoverController willPresentViewController:(UIViewController *)vc{
        #pragma clang diagnostic pop
            self.splitPopoverController = popoverController;
        }
        
        - (BOOL)splitViewController:(UISplitViewController *)splitViewController showDetailViewController:(UIViewController *)vc sender:(nullable id)sender{
            [self.splitPopoverController dismissPopoverAnimated:YES];
            return NO;
        }
        
        @end
        

        【讨论】:

          【解决方案6】:
          @implementation SplitProductView
          
          - (void)viewDidLoad {
              [super viewDidLoad];
              self.delegate = self;
          
          }
          
          
          - (void)viewWillAppear:(BOOL)animated{
              [self resetSplit:[[UIApplication sharedApplication] statusBarOrientation]];
          
              [super viewWillAppear:animated];
          }
          
          -(void)resetSplit :(UIInterfaceOrientation)toInterfaceOrientation {
          
              //TODOX:iphone
              if (isPad)
              {
                  if(UIInterfaceOrientationIsPortrait(toInterfaceOrientation)){
                      self.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryOverlay;
                  }
                  else{
                      //if (self.displayMode == UISplitViewControllerDisplayModePrimaryOverlay)
                      {
                          self.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;
                          self.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
                          self.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic;
          
                      }
                  }
              }
          }
          
          - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
              if (isPad)
              {
                  if (!UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])){
                      self.preferredDisplayMode =UISplitViewControllerDisplayModePrimaryOverlay;
                  }
              }
          
              [self resetSplit:toInterfaceOrientation];
          }
          
          - (void)didReceiveMemoryWarning {
              [super didReceiveMemoryWarning];
              // Dispose of any resources that can be recreated.
          }
          
          
          - (BOOL)splitViewController:(UISplitViewController *)splitViewController
          collapseSecondaryViewController:(UIViewController *)secondaryViewController
            ontoPrimaryViewController:(UIViewController *)primaryViewController {
              return YES;
          }
          

          【讨论】:

            猜你喜欢
            • 2012-07-27
            • 1970-01-01
            • 2014-05-24
            • 1970-01-01
            • 2015-11-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-09-21
            相关资源
            最近更新 更多