如何隐藏 uitabbarcontroller

我对 UITabBarController有意见。在我的应用程序中,我想隐藏它,但不使用 hidesBottomBarWhenPushed,因为我想隐藏它,而不是当我推它。例如,当我按下应用程序中的“隐藏”按钮时,我想要隐藏它。

我读了很多文章在谷歌,但我不能找出如何我可以做到这一点。

59713 次浏览

在按钮的操作方法中:

[self.tabBarController.tabBar setHidden:YES];

您可以推动模态视图控制器

[self presentModalViewController:myFullscreenViewController animated:YES];

这将创建一个全新的视图全屏幕上方您当前的一个。

dismissModalViewController:animated:解散列表

我从我的工作代码粘贴这个... 你可以调用这些方法来隐藏和显示 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];
}

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

`

ShowTabBar ()对应的 x _ pos 编号是 431271

改进版 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];
}

还修改了代码,以处理在 iOS6中引入的 UIDdevice 方向变化的变化,并确保它正常工作,即使当设备躺在它的背上。

Saurahb 和 karlbecker _ com 的解决方案非常棒,尽管当视图包含 桌景而标签栏动画回放时,它们可以造成明显的弹出效果。我做了一些修改,并将其合并为一个函数(作为 UITabBarController 上的一个类别)。它不是完全完美的(延迟校正动画) ,但是对于表格有很好的效果。

如果你喜欢动画块和类别,给这一个尝试。方向和设备友好。

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:

#import <UIKit/UIKit.h>


@interface UITabBarController (ShowHideBar)


- (void) setHidden:(BOOL)hidden;


@end

用法:

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

下面的解决方案非常适合我,在同样的用例中,我必须使用 TabBar 动画移动到全屏模式。

基本上,这个想法是

  1. 制作 UITabBar的快照;

  2. 将快照的 UIImage加到与 UITabBar具有相同帧的 UIImageView上;

  3. 调整基础视图的大小,并将其放置在 Self. tabBarController.view上;

  4. UITabBar的 alpha 设置为0.0;

  5. UIImageViewUITabBar的快照放在 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;
    }
    

这是 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();
}

@ karlbecker _ com 回答对于 iPhone4和 iPhone5来说都是完美的。如果有人对底部的 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];
}

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

最后,我的解决方案相当简单: 扩展屏幕底部的 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];
}

然后,为了在用户弹出到 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];
}
}
}

在 iOS8中,仅仅设置 tabBarhidden属性就足够了
就像在 Swift 里一样

rootTabVC = UITabBarController()
rootTabVC?.tabBar.hidden = true

我在 appdelegate中的 didFinishLaunchingWithOptions中做了这个,它工作得很好,我想如果我没有记错的话,在旧的 iOS 版本中,你还需要将 tabBarframe设置为屏幕之外的某个东西,否则 tabbar将不会显示,但它仍然会占据空间。

自 IOS 7.1以来,“迅捷”解决方案:

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

希望这个能帮上忙!

迅速和修改版本的@Saurabh 代码

方法

func setTabBarHidden (bool:Bool){
for view in tabBarController!.view.subviews {
if (view.isKindOfClass(UITabBar)){
let tabBar = view as! UITabBar
UIView.animateWithDuration(0.3, animations: { () -> Void in
var offset = CGFloat(50)
if (bool == false){
offset = -50;
}
tabBar.frame = CGRect(origin: CGPointMake(tabBar.frame.origin.x, tabBar.frame.origin.y + offset), size: tabBar.frame.size)
})
}
}
}

展示

override func viewDidLoad() {
setTabBarHidden(true)
}

藏起来

override func viewWillDisappear(animated: Bool) {
setTabBarHidden(false)
}

更新和工作的迅速5和 ios 14.0

/*
Shows or hides the tabbar


:param: hidden            whether to show or hide the tabbar
:param: animationDuration the animation's duration
*/
extension UITabBarController {
func setHidden(hidden:Bool, animationDuration:TimeInterval = 0.25) {
        

let screenRect = UIScreen.main.bounds
var fHeight = screenRect.size.height
        

if !hidden {
fHeight -= self.tabBar.frame.size.height
}
        

UIView.animate(withDuration: animationDuration, animations: {
for view in self.view.subviews {
if view is UITabBar {
view.frame = CGRect(
x: view.frame.origin.x,
y: fHeight,
width: view.frame.size.width,
height: view.frame.size.height)
}
}
})
}
}

这是一个更直接的端口(未经测试) :

/*
Shows or hides the tabbar


:param: hidden            whether to show or hide the tabbar
:param: animationDuration the animation's duration
*/
extension UITabBarController {
func setHidden(hidden:Bool, animationDuration:TimeInterval = 0.25) {
        

let screenRect = UIScreen.main.bounds
var fHeight = screenRect.size.height
        

if UIApplication.shared.statusBarOrientation.isLandscape {
fHeight = screenRect.size.width
}
        

if !hidden {
fHeight -= self.tabBar.frame.size.height
}
        

UIView.animate(withDuration: animationDuration, animations: {
for view in self.view.subviews {
if view is UITabBar {
view.frame = CGRect(
x: view.frame.origin.x,
y: fHeight,
width: view.frame.size.width,
height: view.frame.size.height)
}
else if hidden {
view.frame = CGRect(
x: view.frame.origin.x,
y: view.frame.origin.y,
width: view.frame.size.width,
height: fHeight)
}
}
}, completion: { finished in
if !hidden {
UIView.animate(withDuration: animationDuration, animations: {
for view in self.view.subviews {
if !(view is UITabBar) {
view.frame = CGRect(
x: view.frame.origin.x,
y: view.frame.origin.y,
width: view.frame.size.width,
height: fHeight)
}
}
})
}
})
}
}

隐藏选项卡栏不是一个适当的解决方案,它不会调整当前视图控制器的视图高度。

相反,您可以简单地转换标签栏本身,通过它的高度(隐藏)或身份转换重置为可见。

extension UITabBarController {
func setBarHiddenAnimated(_ hidden:Bool) {
UIView.animate(withDuration: 0.3, animations: {
if hidden {
self.tabBar.transform = CGAffineTransform(translationX: 0, y: self.tabBar.frame.size.height)
} else {
self.tabBar.transform = CGAffineTransform.identity
}
})
}
}

注意,您可能需要将视图控制器设置为“在底部条形图下延伸”和“在不透明条形图下延伸”,以便在动画过程中移除黑色背景。

一个带有动画的快速版本,你需要自己设置一个属性 isHideTabBar

self.isHideTabBar = !self.isHideTabBar
UIView.animate(withDuration: 0.5, animations: {
self.tabBarController?.tabBar.frame = (self.tabBarController?.tabBar.frame.offsetBy(dx: 0, dy: self.isHideTabBar ? 100 : -100))!
})