在UISplitViewController中为横向模式下的一个视图控制器设置主视图启用显示/隐藏

我的应用程序的根视图控制器是UISplitViewController。 主和细节视图控制器是两个导航控制器。 我想要的是,当一个特定的视图控制器在主视图中可见时,我需要隐藏主视图并通过轻扫手势来显示。 在设置根视图控制器之前,当我实现委托方法并将presentWithGesture设置为yes时,它将作为进入导航堆栈的所有视图控制器的正常行为。 但我只需要一个视图控制器。 请分享你的想法。

我以前通过触发一个旋转事件并实现“shouldHideViewController”委托方法来实现这一点。 这样做的最大问题是它很less看起来不错。 有时它看起来有生命力,而有些则只是赶走屏幕。 我写了下面的函数,并把它们放在我的appdelegate中来处理隐藏/显示主。 它隐藏了一个不错的animation,迄今为止我的工作很好(注意:这是我对这个问题的初步回应)。

该function将通过animation调整框架来隐藏/显示masterViewController。 你也可以在animation完成时传递一个完成块来调用,因为调用控制器需要按顺序做animation,以便视图很好的布局。 如果不需要,通过零。 请注意,使用自动布局时,这也是最好的。

#pragma mark - UISplitView Hide Master /** Will hide/show masterViewController by adjusting it's frame with an animation. * Can pass a completion block to be called when the animation is finished incase calling * controller needs to do animations in-order for view. Pass nil if not needed. @param completionBlock - accepts an optional completion block or nil arguement. The completion block is called when the hide/unhide animation is complete. @return void */ -(void)toggleHideMaster:(void(^)(void))completionBlock { __weak MyAppDelegate *delegate = self; __weak UISplitViewController *splitView = (UISplitViewController*)self.window.rootViewController; // Adjust the detailView frame to hide/show the masterview [UIView animateWithDuration:0.20f delay:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:^(void) { CGRect selfFrame = splitView.view.frame; // Get the width of the master view controller - so we know how far to animate. CGFloat deltaWidth = delegate.masterNavigationController.topViewController.view.frame.size.width; if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) { if (!delegate.masterIsHidden) { selfFrame.size.width += deltaWidth; selfFrame.origin.x -= deltaWidth; } else { selfFrame.size.width -= deltaWidth; selfFrame.origin.x += deltaWidth; } } else { if(!delegate.masterIsHidden) { selfFrame.size.height += deltaWidth; if (splitView.interfaceOrientation == UIInterfaceOrientationLandscapeRight) { selfFrame.origin.y -= deltaWidth; } } else { selfFrame.size.height -= deltaWidth; if (splitView.interfaceOrientation == UIInterfaceOrientationLandscapeRight) { selfFrame.origin.y += deltaWidth; } } } [splitView.view setFrame:selfFrame]; }completion:^(BOOL finished){ if (finished) { delegate.masterIsHidden = !delegate.masterIsHidden; if (completionBlock) { completionBlock(); } } }]; } /** Method is called by the Navigation controller when the ipad is rotated. Also called when we come from the background incase we were in a full screen state. This is to get the master controller back into the correct state. @return void */ - (void)updateHideMasterOnRotation { if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) { if (self.masterIsHidden) { self.masterIsHidden = NO; [self toggleHideMaster:nil]; } } } // I observe the rotation in my detailview's navigationcontroller like this. // We track this on the navigation controller to globally reset the master hidden state to where it needs to be. This won't take into account previously passed completion blocks. If needed that can be handled in the view controller implementing the hideable splitview. // Again - additional things will need to be considered if supporting portrait - like resetting if we rotate to a portrait orientation. - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { MYAppDelegate *appDelegate = (MYAppDelegate*)[UIApplication sharedApplication].delegate; [appDelegate updateHideMasterOnRotation]; } 

现在你有一个模式,将隐藏animation的主视图,并可以由任何viewcontroller调用。 此示例适用于横向locking的应用程序,但同时支持横向旋转(FYI),您可以更新模式以使用less量条件纵向工作。 这也允许简单的方法来实现这个function。 之前我曾经看过MGSplitviewcontroller,虽然很棒,但我不需要它提供的所有function。 当我不需要大部分他们所做的事情时,我也不喜欢让依赖于别人的依赖更新。

编辑12/10 – 增加了iOS8支持这个答案。 在iOS7中,splitview框架的xy坐标是相反的。 在iOS8,他们是你所期望的。 所以我们现在需要考虑到这一点。 iOS8中的框架也没有改变,所以我们只在iOS <8.0的时候更新。

希望这可以帮助别人。

快乐的编程。