Iphone:可以隐藏TabBar吗? (iOS 8之前)

时间:2009-12-30 20:06:34

标签: iphone ios objective-c uitabbarcontroller

我有一个使用UITabBarController在模式之间切换的应用程序。在某种模式下,我想隐藏标签栏,直到该模式的步骤完成。请注意,我没有使用导航控制器,因此我无法使用导航控制器上的setHidesBottomBarWhenPushed方法隐藏标签栏。

在iOS 8之前,当我尝试使用以下方法隐藏tarbar时

self.tabBarController.tabBar.hidden = YES

标签栏消失,但它在屏幕底部留下了一个50像素的空白区域,标签栏曾经是这样。我似乎无法弄清楚如何填补该区域。用户界面中该区域内的任何内容都会被裁剪,无法看到。

任何想法,如果这是可能的?我真的很想远离导航控制器。

16 个答案:

答案 0 :(得分:37)

这是我的代码:

当然,这与控制器视图层次结构中的 goings on 相混淆。它可以改变/破坏。这使用定义的API,因此Apple不会关心,但他们也不会在意破坏您的代码。

- (void)hideTabBar {
  UITabBar *tabBar = self.tabBarController.tabBar;
  UIView *parent = tabBar.superview; // UILayoutContainerView
  UIView *content = [parent.subviews objectAtIndex:0];  // UITransitionView
  UIView *window = parent.superview;

  [UIView animateWithDuration:0.5
                   animations:^{
                     CGRect tabFrame = tabBar.frame;
                     tabFrame.origin.y = CGRectGetMaxY(window.bounds);
                     tabBar.frame = tabFrame;
                     content.frame = window.bounds;
                   }];

  // 1
}

- (void)showTabBar {
  UITabBar *tabBar = self.tabBarController.tabBar;
  UIView *parent = tabBar.superview; // UILayoutContainerView
  UIView *content = [parent.subviews objectAtIndex:0];  // UITransitionView
  UIView *window = parent.superview;

  [UIView animateWithDuration:0.5
                   animations:^{
                     CGRect tabFrame = tabBar.frame;
                     tabFrame.origin.y = CGRectGetMaxY(window.bounds) - CGRectGetHeight(tabBar.frame);
                     tabBar.frame = tabFrame;

                     CGRect contentFrame = content.frame;
                     contentFrame.size.height -= tabFrame.size.height;
                   }];

  // 2
}

修改: 一位匿名用户建议为7.0添加以下内容(我没有对此进行测试,也无法说明它是变通方法还是理想的实现方式):

// 1. To Hide the black line in IOS7 only, this extra bit is required
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
    [self.tabBarController.tabBar setTranslucent:YES];
}  

// 2. For IOS 7 only
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
    [self.tabBarController.tabBar setTranslucent:NO];
}

修改:在8.x中完全未经测试,可能缺少某些布局。

答案 1 :(得分:9)

像史蒂夫一样,我还没有找到一个干净的方法来做到这一点(尽管Apple Photopicker做了类似的事情)。这就是我所做的:

 if (systemAction)
  {
    // Reveal tab bar back
    CGRect bounds = [[UIScreen mainScreen] bounds];
    CGRect tabBarFrame = self.tabBarController.tabBar.frame;
    self.tabBarController.view.frame = CGRectMake(0,0,bounds.size.width,bounds.size.height);
    self.toolBar.hidden = YES;
    systemAction = NO;
  }
  else
  {
    //hide tab bar
    CGRect bounds = [[UIScreen mainScreen] bounds];
    CGRect tabBarFrame = self.tabBarController.tabBar.frame;
    CGRect navigationBarFrame = self.navigationController.navigationBar.frame;
    self.tabBarController.view.frame = CGRectMake(0,0,bounds.size.width,bounds.size.height+tabBarFrame.size.height);
    self.toolBar.hidden = NO;
    CGRect frame = self.toolBar.frame;
    frame.origin.y = bounds.size.height - frame.size.height - navigationBarFrame.size.height;
    self.toolBar.frame = frame;
    systemAction = YES;
  }

它正在做的是将视图向下推,这样我就可以显示一个工具栏(而不是隐藏它)。显然,这仅适用于tabbar +导航控制器的“根视图”。对于任何后续视图,您可以在要推动的视图控制器上设置“hidesBottomBarWhenPushed”。

答案 2 :(得分:8)

我尝试了上面的一些解决方案,但在iOS 8中没有任何乐趣。我发现viewWillAppear中的设置对我来说有以下作用。应该在iOS 7中工作,因为然后引入了extendedLayoutIncludesOpaqueBars。

    self.extendedLayoutIncludesOpaqueBars = true
    self.tabBarController?.tabBar.isHidden = true
    self.tabBarController?.tabBar.isOpaque = true

如果您需要在viewWillDisappear中使用以下内容时再次打开tabBars。

    self.tabBarController?.tabBar.isHidden = false
    self.tabBarController?.tabBar.isOpaque = false

我使用它来允许从过渡返回以保持TabBar隐藏。没有在按钮动作中使用它,但如果像我一样,你发现现在没有任何东西可以工作,这可能是可编程解决方案的基础。

答案 3 :(得分:4)

当天有点晚了,但是在我今天下午搜遍的问题的所有答案中,这个对我来说效果最好。

How to hide uitabbarcontroller

// Method call
[self hideTabBar:self.tabBarController];   

// Method implementations
- (void)hideTabBar:(UITabBarController *) tabbarcontroller
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];

    for(UIView *view in tabbarcontroller.view.subviews)
    {
        if([view isKindOfClass:[UITabBar class]])
        {
            [view setFrame:CGRectMake(view.frame.origin.x, 480, view.frame.size.width, view.frame.size.height)];
        } 
        else 
        {
            [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 480)];
        }
    }

    [UIView commitAnimations];   
}

- (void)showTabBar:(UITabBarController *) tabbarcontroller
{       
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];
    for(UIView *view in tabbarcontroller.view.subviews)
    {
        NSLog(@"%@", view);

        if([view isKindOfClass:[UITabBar class]])
        {
            [view setFrame:CGRectMake(view.frame.origin.x, 431, view.frame.size.width, view.frame.size.height)];

        } 
        else 
        {
            [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 431)];
        }
    }

    [UIView commitAnimations]; 
}

答案 4 :(得分:4)

我只使用这一行来实现这一目标。在显示具有标签栏的视图控制器之前,我使用prepareForSegue方法。

-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if([segue.identifier isEqualToString:@"showLogin"]){
        [segue.destinationViewController setHidesBottomBarWhenPushed:YES];
    }
}

答案 5 :(得分:3)

我曾经处理过几乎相同的案例,实际上使用了来自http://www.developers-life.com/hide-uitabbarcontrolleruitabbar-with-animation.html的代码,并根据我的需要使其更好,这也可能对其他人有所帮助。

我使用UISplitViewController作为根视图控制器,其细节部分是UITabBarController,我不得不以纵向模式隐藏tabbar:

// In UITabBarController's custom implementation add following method, 
// this method is all that will do the trick, just call this method 
// whenever tabbar needs to be hidden/shown 
- (void) hidetabbar:(NSNumber*)isHidden {
    UITabBarController *tabBarController=self;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];

    CGRect tabbarFrame=CGRectZero;
    for(UIView *theView in tabBarController.view.subviews) {
        //NSLog(@"%@", view);
        if([theView isKindOfClass:[UITabBar class]]) {
            tabbarFrame=theView.frame;
            if ([isHidden boolValue]) {
                tabbarFrame=CGRectMake(tabbarFrame.origin.x, 
                                       tabBarController.view.frame.size.height, 
                                       tabbarFrame.size.width, 
                                       tabbarFrame.size.height);
            } else {
                tabbarFrame=CGRectMake(tabbarFrame.origin.x, 
                                       tabBarController.view.frame.size.height - tabbarFrame.size.height, 
                                       tabbarFrame.size.width,
                                       tabbarFrame.size.height);
            }
            theView.frame=tabbarFrame;
            break;
        }
    }

    for(UIView *theView in tabBarController.view.subviews) {
        if(![theView isKindOfClass:[UITabBar class]]) {
            CGRect theViewFrame=theView.frame;
            if ([isHidden boolValue]) {
                theViewFrame=CGRectMake(theViewFrame.origin.x, 
                                        theViewFrame.origin.y, 
                                        theViewFrame.size.width, 
                                        theViewFrame.size.height + tabbarFrame.size.height);
            } else {
                theViewFrame=CGRectMake(theViewFrame.origin.x, 
                                        theViewFrame.origin.y, 
                                        theViewFrame.size.width, 
                                        theViewFrame.size.height - tabbarFrame.size.height);
            }
            theView.frame=theViewFrame;
        }
    }
    [UIView commitAnimations];
}

我使用以下代码调用hidetabbar:method

//In my UISplitViewController's custom implementation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    @synchronized(self){
    //change the self.splitDetailController to your UITabBarController's object
    [self.splitDetailController 
     performSelector:@selector(hidetabbar:) 
     withObject:[NSNumber numberWithBool:UIInterfaceOrientationIsLandscape(interfaceOrientation)]
     afterDelay:0.5];
    }
    return YES;
}

我测试了这段代码只在模拟器中工作,让我知道它是否也能在设备上工作; - )

答案 6 :(得分:0)

您是否在子视图上设置了autoResizingMask?

view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

这样的事情可以解决问题,并允许坐在堆栈顶部的视图重新调整大小。

答案 7 :(得分:0)

保持原始架构的显而易见的解决方案是以模态方式呈现该视图:

- (void)tabBarController:(UITabBarController *)tb
 didSelectViewController:(UIViewController *)vc {
    if (tb.selectedIndex == MODALONE) {
        UIViewController* mod = 
            [[UIViewController alloc] initWithNibName: @"ModalView" 
                                               bundle: nil];
        [tb presentModalViewController:mod animated:NO];
        [mod release];
    }
}

视图现在覆盖整个屏幕(状态栏除外),包括标签栏,因此看起来标签栏已经消失,以响应用户按下该标签栏项目。

答案 8 :(得分:0)

autoresizing mask有一个枚举。尝试设置所有选项并检查是否在父视图中选中了自动调整子视图选项

答案 9 :(得分:0)

您可以轻松创建Tabbar类别并显示/隐藏。并且您可以访问完整视图。

创建类别#import "UITabBarController+HideTabBar.h"

@implementation UITabBarController (HideTabBar)

- (void)hideTabBarAnimated:(BOOL)animated
{
    CGRect statusbarFrame = [UIApplication sharedApplication].statusBarFrame;
    CGRect tabBarControllerFrame = self.view.frame;
    if (statusbarFrame.size.height>20)
    {
        tabBarControllerFrame.size.height =  screenSize.size.height + self.tabBar.frame.size.height - 20.0;
    }
    else
    {
        tabBarControllerFrame.size.height = screenSize.size.height + self.tabBar.frame.size.height ;
    }

    if (animated) {
        [UIView animateWithDuration:0.2 animations:^{
            [self.view setFrame:tabBarControllerFrame];
        } completion:^(BOOL finished) {

        }];
    }
    else
        [self.view setFrame:tabBarControllerFrame];
}

- (void)showTabBarAnimated:(BOOL)animated {
    CGRect statusbarFrame = [UIApplication sharedApplication].statusBarFrame;
    CGRect tabBarControllerFrame = self.view.frame;
    if (statusbarFrame.size.height>20)
    {
        tabBarControllerFrame.size.height =  screenSize.size.height - 20.0;
    }
    else
    {
        tabBarControllerFrame.size.height = screenSize.size.height ;
    }

    if (animated) {
        [UIView animateWithDuration:0.2 animations:^{
            [self.view setFrame:tabBarControllerFrame];
        } completion:^(BOOL finished) {

        }];
    }
    else
        [self.view setFrame:tabBarControllerFrame];
}
@end

注意 hotspot 调用为ON时使用statusbarFrame,因此tabbar不会缩减。

现在导入您想要使用方法的类别,只需调用以下方法来隐藏或显示标签栏。

[self.tabBarController hideTabBarAnimated:YES];

[self.tabBarController showTabBarAnimated:YES];

希望这有助于。

答案 10 :(得分:0)

希望这有效。

@interface UITabBarController (Additions)

-(void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated;

@end

@implementation UITabBarController (Additions)

-(void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated
{
    if (animated)
    {
        [UIView beginAnimations:nil context:nil];
    }
    if (hidden)
    {

        self.tabBar.frame = CGRectMake(self.tabBar.frame.origin.x, self.tabBar.superview.frame.size.height, self.tabBar.bounds.size.width, self.tabBar.bounds.size.height);
    }
    else
    {
        self.tabBar.frame = CGRectMake(self.tabBar.frame.origin.x, self.tabBar.superview.frame.size.height - self.tabBar.frame.size.height + 10, self.tabBar.bounds.size.width, self.tabBar.bounds.size.height);
    }
    if (animated)
    {
        [UIView commitAnimations];
    }

}

答案 11 :(得分:0)

这是我的解决方案(我的选项卡视图控制器位于导航控制器内部以便进行测量)...所以我已经将UITabBarController子类化并执行此操作...公开-setTabBarHidden:方法

- (void)setTabBarHidden:(BOOL)hidden {
    _tabBarHidden = hidden;

    [UIView performWithoutAnimation:^{
        [self adjustViews];
    }];

}

- (void)adjustViews {
    if ( _tabBarHidden ) {
        CGRect f = self.tabBar.frame;

        // move tab bar offscreen
        f.origin.y = CGRectGetMaxY(self.view.frame);
        self.tabBar.frame = f;

        // adjust current view frame
        self.selectedViewController.view.frame = self.view.frame;
    } else {
        CGRect f = self.tabBar.frame;

        // move tab bar on screen
        f.origin.y = CGRectGetMaxY(self.view.frame) - (CGRectGetMaxY(self.tabBar.bounds) + CGRectGetMaxY(self.navigationController.navigationBar.frame));
        self.tabBar.frame = f;

        // adjust current view frame
        f = self.view.bounds;
        f.size.height -= CGRectGetMaxY(self.tabBar.bounds);
        self.selectedViewController.view.frame = f;
    }
}

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    [UIView performWithoutAnimation:^{
        [self adjustViews];
    }];
}

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    [UIView performWithoutAnimation:^{
        [self adjustViews];
    }];
}

答案 12 :(得分:0)

将语句放在UIViewController的

的init方法中
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        self.hidesBottomBarWhenPushed = true
        setupDependencyConfigurator()
    }

答案 13 :(得分:-1)

见这个帖子:

Show/Hide TabBarController in iphone

总之,您可以在此示例代码中看到此行为的示例:

http://developer.apple.com/iphone/library/samplecode/TheElements/index.html

答案 14 :(得分:-3)

为什么不使用导航控制器。隐藏导航栏比标签栏容易得多......

答案 15 :(得分:-3)

刚刚在Monotouch中在UITabBarController的子类中创建了以下代码:

    public void ShowTabBar()
    {
        UIView.BeginAnimations("Anim");
        UIView.SetAnimationDuration(0.25f);
        this.View.Subviews[0].Frame = new RectangleF(0f, 0f, 320f, 431f);
        this.TabBar.Frame = new RectangleF(0f, 431f, 320f, 49f);
        this.TabBar.Hidden = false;
        UIView.CommitAnimations();
    }

    public void HideTabBar()
    {
        UIView.BeginAnimations("Anim");
        UIView.SetAnimationDuration(0.25f);
        this.View.Subviews[0].Frame = new RectangleF(0f, 0f, 320f, 480f);
        this.TabBar.Frame = new RectangleF(0f, 481f, 320f, 510f);
        this.TabBar.Hidden = true;
        UIView.CommitAnimations();          
    }