在UISplitViewController中为横向模式中的一个视图控制器设置显示/隐藏以显示主视图 [英] Set show/hide for master view enable in UISplitViewController for only one view controller in landscape mode

查看:109
本文介绍了在UISplitViewController中为横向模式中的一个视图控制器设置显示/隐藏以显示主视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

My App的Root视图控制器是UISplitViewController。
主视图和详细视图控制器是两个导航控制器。
我想要的是,当一个特定的视图控制器在主视图中可见时,我需要通过滑动手势隐藏和显示主视图。
当我在设置根视图控制器之前实现委托方法并将presentWithGesture设置为yes时,它将作为导航堆栈上所有视图控制器的正常行为。但我只需要一个视图控制器。请分享您的任何想法。

My App's Root view controller is UISplitViewController. Master and Detail view controllers are two navigation controllers. What I want is, when a particular view controller gets visible in master view, I need master view to be hidden and show-able by swipe gesture. When I implement delegate methods and set presentWithGesture to yes before setting the root view controller, it works as its normal behavior for all the view controllers coming on navigation stack. But I need it only for for one view controller. Please share any idea you have.

推荐答案

我之前通过触发旋转事件并实现shouldHideViewController委托方法来实现此目的。这样做的最大问题是它很少看起来很好。有时它似乎有动画,而有些它只是匆匆离开屏幕。我编写了下面的函数并将它们放在我的appdelegate中来处理隐藏/显示主人的问题。它隐藏着一个很好的动画,并且对我来说效果很好(注意:这是我对这个问题的初步回答的编辑)。

I previously accomplished this by triggering a rotation event and implementing the "shouldHideViewController" delegate method. The biggest issue with doing it that way is that it rarely looks good. Sometimes it appears to animate, while others it just hurries off the screen. I wrote the below functions and placed them in my appdelegate to handle hiding/showing the master. It hides with a nice animation and has worked nicely for me so far (note: this is an edit of my preliminary response to this question).

这个函数会隐藏/通过动画调整它的框架来显示masterViewController。
你也可以传递一个完成块,当动画完成时调用它,因为调用控制器需要按顺序进行动画处理,以便它可以很好地进行布局。如果不需要,通过nil。请注意,使用autolayout时这也最有效。

This function Will hide/show masterViewController by adjusting it's frame with an animation. you can also pass a completion block to be called when the animation is finished incase calling controller needs to do animations in-order for it's view to layout nicely. Pass nil if not needed. Note that this also works best when using autolayout.

#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];
}

现在你有一个模式可以用动画隐藏主视图,可以是由任何viewcontroller调用。此示例适用于在横向上锁定但支持横向旋转(FYI)的应用程序,您可以使用一些条件更新模式以纵向工作。这也允许对此功能采用简约方法。我之前看过MGSplitviewcontroller,虽然很棒,但我并不需要它提供的所有功能。当我不需要他们的大部分工作时,我也不喜欢依赖别人更新的依赖项。

Now you have a pattern that will hide the master view with animation and can be called by any viewcontroller. This example is for an app that is locked in landscape, but supports both landscape rotations (FYI), you could update the pattern to work in portrait with a few conditionals. This also allows a minimalistic approach to this functionality. I have looked at MGSplitviewcontroller before, and while it's wonderful, I don't need all the functionality it provides. I also don't like having dependencies that are dependent on others to update when I don't need most of what they do.

编辑12/10 - 增加了iOS8支持这个答案。在iOS7中,splitview框架的xy坐标被颠倒了。在iOS8中,它们就像您期望的那样。所以我们现在需要考虑到这一点。在iOS8中,框架在旋转时也保持不变,因此我们仅在iOS中的旋转时更新< 8.0。

Edit 12/10 - Added iOS8 support to this answer. In iOS7, the xy coords for the splitview's frame were reversed. In iOS8 they are as you would expect. So we now need to take this into account. The frame is also unchanged on rotation in iOS8, so we only update on rotation in iOS < 8.0.

希望这可以帮助别人。

快乐编程。

这篇关于在UISplitViewController中为横向模式中的一个视图控制器设置显示/隐藏以显示主视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆