ios 如何隐藏uitabbarcontroller

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5272290/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:11:56  来源:igfitidea点击:

How to hide uitabbarcontroller

iphoneiosuitabbarcontroller

提问by Viktor Apoyan

I have a problem with UITabBarController. In my application, I want to hide it but without using hidesBottomBarWhenPushedbecause I want to hide it not when I pushed it. For Example, I want to hide it when I press a Hide button in my application.

我有问题UITabBarController。在我的应用程序中,我想隐藏它但不使用它,hidesBottomBarWhenPushed因为我不想在推送它时隐藏它。例如,当我按下应用程序中的隐藏按钮时,我想隐藏它。

I read many articles in google but I cant find out how I can do this.

我在谷歌上阅读了很多文章,但我不知道如何做到这一点。

回答by Saurabh

I am pasting this from my working code... you can call these methods to hide and show the tabbarcontroller.... just pass tabbarcontroller instance to these functions..

我正在从我的工作代码中粘贴这个......你可以调用这些方法来隐藏和显示 tabbarcontroller......只需将 tabbarcontroller 实例传递给这些函数......

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

回答by karlbecker_com

Modified Setomidor's answer to work on both landscape, portrait, and iPad (the 320 and 480 values only work on iPhone).

修改了 Setomidor 的答案,使其适用于横向、纵向和 iPad(320 和 480 值仅适用于 iPhone)。

- (void) hideTabBar:(UITabBarController *) tabbarcontroller 
{
    CGRect screenRect = [[UIScreen mainScreen] bounds];

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];
    float fHeight = screenRect.size.height;
    if(  UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) )
    {
        fHeight = screenRect.size.width;
    }

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



- (void) showTabBar:(UITabBarController *) tabbarcontroller 
{   
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    float fHeight = screenRect.size.height - tabbarcontroller.tabBar.frame.size.height;

    if(  UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) )
    {
        fHeight = screenRect.size.width - tabbarcontroller.tabBar.frame.size.height;
    }

    [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, fHeight, view.frame.size.width, view.frame.size.height)];            
        } 
        else 
        {
            [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
        }       
    }
    [UIView commitAnimations]; 
}

Also modified the code to handle changes introduced in iOS 6 with UIDevice orientation change and ensure that it works properly even when the device is lying on its back.

还修改了代码以处理 iOS 6 中引入的 UIDevice 方向更改,并确保即使设备平躺也能正常工作。

回答by Sailesh

In your action method for the button:

在按钮的操作方法中:

[self.tabBarController.tabBar setHidden:YES];

回答by Thomas Verbeek

Saurahb and karlbecker_com's solutions are great, though they can cause an obvious popping effect when the view contains a tableviewwhile the tab bar animates back up. I've made some modifications and combined it into a single function (as a category on UITabBarController). It's not completely perfect (delayed correction animation) but gives good results with tables.

Saurahb 和 karlbecker_com 的解决方案很棒,尽管当视图包含tableview而标签栏动画备份时,它们会导致明显的弹出效果。我做了一些修改并将它组合成一个单一的函数(作为 UITabBarController 上的一个类别)。它并不完全完美(延迟校正动画),但在表格中给出了很好的结果。

If you like animation blocks and categories, give this a try. Orientation and device friendly.

如果您喜欢动画块和类别,请尝试一下。方向和设备友好。

UITabBarController+ShowHideBar.m:

UITabBarController+ShowHideBar.m:

#import "UITabBarController+ShowHideBar.h"

@implementation UITabBarController (ShowHideBar)

- (void) setHidden:(BOOL)hidden{

    CGRect screenRect = [[UIScreen mainScreen] bounds];
    float fHeight = screenRect.size.height;
    if(  UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) ){
        fHeight = screenRect.size.width;
    }

    if(!hidden) fHeight -= self.tabBar.frame.size.height;

    [UIView animateWithDuration:0.25 animations:^{
        for(UIView *view in self.view.subviews){
            if([view isKindOfClass:[UITabBar class]]){
                [view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
            }else{
                if(hidden) [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
            }
        }
    }completion:^(BOOL finished){
        if(!hidden){

            [UIView animateWithDuration:0.25 animations:^{

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

            }];
        }
    }];

}

@end

UITabBarController+ShowHideBar.h:

UITabBarController+ShowHideBar.h:

#import <UIKit/UIKit.h>

@interface UITabBarController (ShowHideBar)

- (void) setHidden:(BOOL)hidden;

@end

Usage:

用法:

[self.tabBarController setHidden:YES];
[self.tabBarController setHidden:NO];

回答by Setomidor

Saurabh's answer above can be extended to also work in landscape orientation:

上面 Saurabh 的答案可以扩展到也适用于横向:

+ (void) hideTabBar:(UITabBarController *) tabbarcontroller {

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

    //Support for landscape views
    int orientation = [[UIDevice currentDevice] orientation];
    int x_pos = 480;
    if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
        x_pos = 320;
    }

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

`

`

The corresponding x_pos numbers for showTabBar() are 431and 271.

showTabBar() 对应的 x_pos 数字是431271

回答by Diego

This is karlbecker_com's answer, ported to MonoTouch (Xamarin.iOS). The only difference is that I implemented the methods on a class that inherits from UITabBarController, so references to "tabbarcontroller" were replaced by "this".

这是 karlbecker_com 的答案,移植到 MonoTouch (Xamarin.iOS)。唯一的区别是我在继承自 UITabBarController 的类上实现了这些方法,因此对“ tabbarcontroller”的引用被替换为“ this”。

public void HideTabBar()
{
    var screenRect = UIScreen.MainScreen.Bounds;
    float fHeight = screenRect.Height;
    if(UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeLeft
       || UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeRight)
    {
        fHeight = screenRect.Width;
    }

    UIView.BeginAnimations(null);
    UIView.SetAnimationDuration(0.4);
    foreach(UIView view in this.View.Subviews)
    {
        if(view is UITabBar)
        {
            view.Frame = new RectangleF(view.Frame.X, fHeight, view.Frame.Width, view.Frame.Height);
        } 
        else 
        {
            view.Frame = new RectangleF(view.Frame.X, view.Frame.Y, view.Frame.Width, fHeight);
            view.BackgroundColor = UIColor.Black;
        }
    }
    UIView.CommitAnimations();
}

public void ShowTabBar()
{   
    var screenRect = UIScreen.MainScreen.Bounds;
    float fHeight = screenRect.Height - 49f;
    if(UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeLeft
       || UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeRight)
    {
        fHeight = screenRect.Width - 49f;
    }

    UIView.BeginAnimations(null);
    UIView.SetAnimationDuration(0.4);
    foreach(UIView view in this.View.Subviews)
    {
        if(view is UITabBar)
        {
            view.Frame = new RectangleF(view.Frame.X, fHeight, view.Frame.Width, view.Frame.Height);
        } 
        else 
        {
            view.Frame = new RectangleF(view.Frame.X, view.Frame.Y, view.Frame.Width, fHeight);
        }
    }
    UIView.CommitAnimations();
}

回答by mikemike396

@karlbecker_com Answer works perfect for both the iPhone 4 and iPhone 5. If anyone is having issues with iOS7 black bar at the bottom set the tabBarController to translucent

@karlbecker_com 答案适用于 iPhone 4 和 iPhone 5。如果有人遇到 iOS7 底部黑条的问题,请将 tabBarController 设置为半透明

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

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

回答by Sifeng

Since IOS 7.1, "Swift"solutions:

自 IOS 7.1 起,“Swift”解决方案:

self.tabBarController?.tabBar.hidden = true // hide tabbar
self.tabBarController?.tabBar.hidden = false // show tabbar

Hope this could help!

希望这会有所帮助!

回答by Yevhen Dubinin

The solution below works fine for me in exactly the same use case where I have to move to fullscreen mode with TabBar animation.

在我必须使用 TabBar 动画切换到全屏模式的完全相同的用例中,下面的解决方案对我来说很好用。

Basically, the idea is

基本上,这个想法是

  1. to make a snapshot of UITabBar;

  2. add the UIImageof the snapshot to UIImageViewwhich has the same frame as UITabBardoes;

  3. resize underlying view and place it on self.tabBarController.view;

  4. set UITabBar's alpha to be 0.0;

  5. place the UIImageViewwith UITabBar's snapshot on the self.tabBarController.view;

  6. Once the above is achieved, do any kind of animation

    #import "QuartzCore/CALayer.h"
    
    @implementation FTBFirstViewController {
       BOOL hidden;
       UIImageView *fakeTabBarImageView;
       UIView *viewToResize;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        //////////////////////////////
        // Create your viewToResize
        //////////////////////////////
        [self.view addSubview:viewToResize];
    
        hidden = NO;
    }
    
    - (void)hideTabBar:(id)sender {
        if (!hidden) {
            //
            // to create the fake UITabBar
            fakeTabBarImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
            UIImage *fakeTabBarImage = [self imageScreenshotFromView:self.tabBarController.tabBar];
            fakeTabBarImageView.image = fakeTabBarImage;
            fakeTabBarImageView.frame = self.tabBarController.tabBar.frame;
            //
            // to resize underlying UIView
            viewToResize.frame = (CGRect){viewToResize.frame.origin.x, viewToResize.frame.origin.y + 20.f, viewToResize.frame.size.width, viewToResize.frame.size.height + fakeTabBarImageView.frame.size.height};
            //
            // to hide real UITabBar
            self.tabBarController.tabBar.alpha = 0.0;
            //
            // to add views in exactly this order
            [self.tabBarController.view addSubview:viewToResize];
            [self.tabBarController.view addSubview:fakeTabBarImageView];
            //
            // do any sort of animation
            [UIView animateWithDuration:0.8 animations:^{
                fakeTabBarImageView.frame = (CGRect){fakeTabBarImageView.frame.origin.x, fakeTabBarImageView.frame.origin.y + fakeTabBarImageView.frame.size.height, fakeTabBarImageView.frame.size};
            }];
    
            hidden = YES;
        } else {
            [UIView animateWithDuration:0.8 animations:^{
                    fakeTabBarImageView.frame = (CGRect){fakeTabBarImageView.frame.origin.x, fakeTabBarImageView.frame.origin.y - fakeTabBarImageView.frame.size.height, fakeTabBarImageView.frame.size};
            } completion:^(BOOL complete){
                self.tabBarController.tabBar.alpha = 1.0;
                [fakeTabBarImageView removeFromSuperview];
                fakeTabBarImageView = nil;
    
                viewToResize.frame = self.view.frame;
                [self.view addSubview:viewToResize];
    
                [fakeTabBarImageView removeFromSuperview];
            }]; 
    
            hidden = NO;
        }
    }
    
    - (UIImage *)imageScreenshotFromView:(UIView *)aView {
        UIImage *viewImage;
    
        UIGraphicsBeginImageContextWithOptions(aView.bounds.size, aView.opaque, [[UIScreen mainScreen] scale]);
        [aView.layer renderInContext:UIGraphicsGetCurrentContext()];
        viewImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return viewImage;
    }
    
  1. 制作UITabBar的快照;

  2. 将快照的UIImage添加到与UITabBar具有相同框架的UIImageView中;

  3. 调整底层视图的大小并将其放在self.tabBarController.view 上

  4. UITabBar的 alpha 设置为 0.0;

  5. 将带有UITabBar快照的UIImageView放在self.tabBarController.view 上

  6. 完成上述操作后,执行任何类型的动画

    #import "QuartzCore/CALayer.h"
    
    @implementation FTBFirstViewController {
       BOOL hidden;
       UIImageView *fakeTabBarImageView;
       UIView *viewToResize;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        //////////////////////////////
        // Create your viewToResize
        //////////////////////////////
        [self.view addSubview:viewToResize];
    
        hidden = NO;
    }
    
    - (void)hideTabBar:(id)sender {
        if (!hidden) {
            //
            // to create the fake UITabBar
            fakeTabBarImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
            UIImage *fakeTabBarImage = [self imageScreenshotFromView:self.tabBarController.tabBar];
            fakeTabBarImageView.image = fakeTabBarImage;
            fakeTabBarImageView.frame = self.tabBarController.tabBar.frame;
            //
            // to resize underlying UIView
            viewToResize.frame = (CGRect){viewToResize.frame.origin.x, viewToResize.frame.origin.y + 20.f, viewToResize.frame.size.width, viewToResize.frame.size.height + fakeTabBarImageView.frame.size.height};
            //
            // to hide real UITabBar
            self.tabBarController.tabBar.alpha = 0.0;
            //
            // to add views in exactly this order
            [self.tabBarController.view addSubview:viewToResize];
            [self.tabBarController.view addSubview:fakeTabBarImageView];
            //
            // do any sort of animation
            [UIView animateWithDuration:0.8 animations:^{
                fakeTabBarImageView.frame = (CGRect){fakeTabBarImageView.frame.origin.x, fakeTabBarImageView.frame.origin.y + fakeTabBarImageView.frame.size.height, fakeTabBarImageView.frame.size};
            }];
    
            hidden = YES;
        } else {
            [UIView animateWithDuration:0.8 animations:^{
                    fakeTabBarImageView.frame = (CGRect){fakeTabBarImageView.frame.origin.x, fakeTabBarImageView.frame.origin.y - fakeTabBarImageView.frame.size.height, fakeTabBarImageView.frame.size};
            } completion:^(BOOL complete){
                self.tabBarController.tabBar.alpha = 1.0;
                [fakeTabBarImageView removeFromSuperview];
                fakeTabBarImageView = nil;
    
                viewToResize.frame = self.view.frame;
                [self.view addSubview:viewToResize];
    
                [fakeTabBarImageView removeFromSuperview];
            }]; 
    
            hidden = NO;
        }
    }
    
    - (UIImage *)imageScreenshotFromView:(UIView *)aView {
        UIImage *viewImage;
    
        UIGraphicsBeginImageContextWithOptions(aView.bounds.size, aView.opaque, [[UIScreen mainScreen] scale]);
        [aView.layer renderInContext:UIGraphicsGetCurrentContext()];
        viewImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return viewImage;
    }
    

回答by SeanR

I tried pretty much all these answers but none of them worked for me. My app has a UITabBarController as the root view, and each tab has a UINavigationController. One of the UINavigationControllers has a UICollectionViewController as the top view controller. When the user selects an item in the UICollectionView, I wanted the detail view controller to get pushed onto the navigation stack. My detail view then had a toolbar at the bottom. I didn't want the toolbar to appear on top of the tab bar as that looks goofy, and switching tab contexts won't be needed from this view. I could probably have easily solved this by manually placing UIToolbars and UITabBars and not using UITabBarController and the built-in UIToolbar, but that seemed like too much refactoring and a bit inelegant.

我几乎尝试了所有这些答案,但没有一个对我有用。我的应用程序有一个 UITabBarController 作为根视图,每个选项卡都有一个 UINavigationController。其中一个 UINavigationControllers 有一个 UICollectionViewController 作为顶视图控制器。当用户在 UICollectionView 中选择一个项目时,我希望细节视图控制器被推送到导航堆栈上。我的详细信息视图底部有一个工具栏。我不希望工具栏出现在选项卡栏的顶部,因为这看起来很傻,并且不需要从此视图切换选项卡上下文。我可以通过手动放置 UIToolbars 和 UITabBars 而不是使用 UITabBarController 和内置的 UIToolbar 来轻松解决这个问题,但这似乎重构太多,有点不优雅。

In the end my solution was fairly simple: extend the bounds of the UITabBarController off the bottom of the screen. I added this to my detail view controller:

最后,我的解决方案相当简单:将 UITabBarController 的边界扩展到屏幕底部。我将此添加到我的详细信息视图控制器中:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    // Extend the UITabBarController to shift the tab bar off screen
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGRect tabBarControllerFrame = self.tabBarController.view.frame;
    if (animated) {
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.5];
        tabBarControllerFrame.size.height = screenRect.size.height +
            self.tabBarController.tabBar.frame.size.height;
        [self.tabBarController.view setFrame:tabBarControllerFrame];
        [UIView commitAnimations];
    }
    else {
        tabBarControllerFrame.size.height = screenRect.size.height +
            self.tabBarController.tabBar.frame.size.height;
        [self.tabBarController.view setFrame:tabBarControllerFrame];
    }

    // Now show the toolbar
    [self.navigationController setToolbarHidden:NO animated:animated];
}

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];

    // Ensure the UITabBarController remains extended when subviews are laid out
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGRect tabBarControllerFrame = self.tabBarController.view.frame;
    tabBarControllerFrame.size.height = screenRect.size.height + 
        self.tabBarController.tabBar.frame.size.height;
    [self.tabBarController.view setFrame:tabBarControllerFrame];
}

Then to reshow the tab bar when the user pops back to the top of my UINavigationController, I added this to my top view controller:

然后当用户弹回到我的 UINavigationController 顶部时重新显示标签栏,我将它添加到我的顶部视图控制器中:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    // Hide toolbar
    [self.navigationController setToolbarHidden:YES animated:animated];

    // Tab bar back on to screen
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGRect tabBarControllerFrame = self.tabBarController.view.frame;
    if (tabBarControllerFrame.size.height != screenRect.size.height) {
        if (animated) {
            [UIView beginAnimations:nil context:NULL];
            [UIView setAnimationDuration:0.5];
            tabBarControllerFrame.size.height = screenRect.size.height;
            [self.tabBarController.view setFrame:tabBarControllerFrame];
            [UIView commitAnimations];
        }
        else {
            tabBarControllerFrame.size.height = screenRect.size.height;
            [self.tabBarController.view setFrame:tabBarControllerFrame];
        }
    }
}