web-dev-qa-db-fra.com

Comment cacher uitabbarcontroller

J'ai un problème avec UITabBarController. Dans mon application, je veux le cacher mais sans utiliser hidesBottomBarWhenPushed car je veux le cacher pas quand je l'ai poussé. Par exemple, je souhaite le masquer lorsque j'appuie sur un bouton Masquer dans mon application. 

J'ai lu de nombreux articles dans Google mais je ne peux pas savoir comment je peux le faire. 

74
Viktor Apoyan

Je colle cela depuis mon code de travail ... vous pouvez appeler ces méthodes pour masquer et afficher le tabbarcontroller .... il suffit de passer une instance de tabbarcontroller à ces fonctions .. 

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

Réponse de Setomidor modifiée pour fonctionner à la fois en mode paysage, portrait et iPad (les valeurs 320 et 480 ne fonctionnent que sur l'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]; 
}

Nous avons également modifié le code pour gérer les modifications introduites dans iOS 6 avec le changement d'orientation UIDevice et garantir son bon fonctionnement même lorsque le périphérique est étendu sur le dos.

58
karlbecker_com

Dans votre méthode d'action pour le bouton:

[self.tabBarController.tabBar setHidden:YES];
34
Sailesh

Les solutions de Saurahb et de karlbecker_com sont excellentes, bien qu'elles puissent provoquer un effet de saut évident lorsque la vue contient une tableview alors que la barre d'onglets s'anime. J'ai apporté quelques modifications et les ai combinées dans une seule fonction (en tant que catégorie sur UITabBarController). Ce n'est pas complètement parfait (animation avec correction différée) mais donne de bons résultats avec les tableaux.

Si vous aimez les blocs et les catégories d'animation, essayez-le. Orientation et appareil convivial.

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

Usage: 

[self.tabBarController setHidden:YES];
[self.tabBarController setHidden:NO];
11
Thomas Verbeek

La réponse de Saurabh ci-dessus peut être étendue pour fonctionner également en orientation paysage:

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

`

Les numéros x_pos correspondants pour showTabBar () sont 431 et 271.

9
Setomidor

C'est la réponse de karlbecker_com, portée sur MonoTouch (Xamarin.iOS) . La seule différence est que j'ai implémenté les méthodes sur une classe qui hérite de UITabBarController, les références à "tabbarcontroller" ont été remplacées par "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();
}
4
Diego

@karlbecker_com Answer fonctionne parfaitement pour l'iPhone 4 et l'iPhone 5. Si quelqu'un a des problèmes avec la barre noire iOS7 en bas, configurez tabBarController sur translucide

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

Depuis IOS 7.1, "Swift" solutions:

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

J'espère que cela pourrait aider!

4
Sifeng

J'ai essayé à peu près toutes ces réponses mais aucune d'entre elles n'a fonctionné pour moi. Mon application a un UITabBarController comme vue racine et chaque onglet a un UINavigationController. L'un des contrôleurs UINavigation a un contrôleur UICollectionViewController en tant que contrôleur de la vue de dessus. Lorsque l'utilisateur sélectionne un élément dans UICollectionView, je souhaitais que le contrôleur de vue de détail soit placé dans la pile de navigation. Ma vue détaillée avait alors une barre d’outils en bas. Je ne voulais pas que la barre d'outils apparaisse au-dessus de la barre d'onglets car cela paraissait bizarre, et il n'est pas nécessaire de changer de contexte d'onglet depuis cette vue. J'aurais probablement pu facilement résoudre ce problème en plaçant manuellement UIToolbars et UITabBars et en n'utilisant pas UITabBarController et le UIToolbar intégré, mais cela semblait trop refactoriser et un peu inélégant.

En fin de compte, ma solution était assez simple: étendre les limites du UITabBarController en bas de l'écran. J'ai ajouté ceci à mon contrôleur de vue de détail:

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

Ensuite, pour afficher à nouveau la barre d'onglets lorsque l'utilisateur revient en haut de mon contrôleur UINavigationController, j'ai ajouté ceci à mon contrôleur de vue supérieure:

- (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];
        }
    }
}
3
SeanR

La solution ci-dessous fonctionne très bien pour moi exactement dans le même cas d’utilisation où je dois passer en mode plein écran avec animation TabBar.

Fondamentalement, l'idée est 

  1. faire un instantané de UITabBar ;

  2. ajoutez le UIImage de l'instantané à UIImageView qui a le même cadre que UITabBar do;

  3. redimensionnez la vue sous-jacente et placez-la sur self.tabBarController.view ;

  4. réglez l'alpha de UITabBar sur 0,0;

  5. placez le snapshot de UIImageView with UITabBar sur le self.tabBarController.view ;

  6. Une fois ce qui précède atteint, faites n'importe quel type d'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;
    }
    
3
Yevhen Dubinin

vous pouvez pousser un contrôleur de vue modale

[self presentModalViewController:myFullscreenViewController animated:YES];

cela créera une vue complètement nouvelle en plein écran au-dessus de votre vue actuelle.

renvoyer ist avec dismissModalViewController:animated:

3
user207616

dans iOS8, il suffit de définir la propriété hidden de tabBar
Comme dans Swift, vous pouvez 

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

Je fais ceci dans mon didFinishLaunchingWithOptions dans le appdelegate et cela fonctionne bien, je pense que si je me souviens bien des versions iOS antérieures, vous deviez également définir le frame du tabBar sur quelque chose en dehors de l'écran, sinon le tabbar ne s'afficherait pas occupent toujours l'espace. 

3
Ali

Version rapide et modifiée du code @Saurabh 

Méthode  

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)
             })   
        }
    }
}

Montrer

override func viewDidLoad() {
     setTabBarHidden(true)
}

Cacher

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

Voici un portage allégé de la version de @Thomas Verbeek de Swift pour les VCs sans tables (testé sous iOS 8.4):

extension UITabBarController {

    /**
    Shows or hides the tabbar

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

        let screenRect = UIScreen.mainScreen().bounds
        var fHeight = screenRect.size.height

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

        UIView.animateWithDuration(animationDuration, animations: {
                for view in self.view.subviews as! [UIView] {
                    if view is UITabBar {
                        view.frame = CGRectMake(
                            view.frame.Origin.x,
                            fHeight,
                            view.frame.size.width,
                            view.frame.size.height)
                    }
                }
            })
    }
}

Et voici le port le plus direct (non testé):

extension UITabBarController {

    /**
    Shows or hides the tabbar

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

        let screenRect = UIScreen.mainScreen().bounds
        var fHeight = screenRect.size.height

        if UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) {
            fHeight = screenRect.size.width
        }

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

        UIView.animateWithDuration(animationDuration, animations: {
                for view in self.view.subviews as! [UIView] {
                    if view is UITabBar {
                        view.frame = CGRectMake(
                            view.frame.Origin.x,
                            fHeight,
                            view.frame.size.width,
                            view.frame.size.height)
                    }
                    else if hidden {
                        view.frame = CGRectMake(
                            view.frame.Origin.x,
                            view.frame.Origin.y,
                            view.frame.size.width,
                            fHeight)
                    }
                }
            }, completion: { finished in
                if !hidden {
                    UIView.animateWithDuration(animationDuration, animations: {
                        for view in self.view.subviews as! [UIView] {
                            if !(view is UITabBar) {
                                view.frame = CGRectMake(
                                    view.frame.Origin.x,
                                    view.frame.Origin.y,
                                    view.frame.size.width,
                                    fHeight)
                            }
                        }
                    })
                }
        })
    }
}
1
svrs

Une version Swift avec animation, vous devez définir vous-même une propriété 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))!
 })
0
William Hu

Masquer la barre d’onglet n’est pas une solution adéquate, cela n’ajustera pas la hauteur de vue actuelle des contrôleurs de vue.

Au lieu de cela, vous pouvez simplement transformer la barre d’onglet elle-même, soit par sa hauteur (pour la cacher), soit par une transformation d’identité pour la rendre visible.

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
            }
        })
    }
}

Notez que vous devrez peut-être régler votre contrôleur de vue sur "s'étend sous les barres inférieures" et "s'étend sous les barres opaques" pour supprimer l'arrière-plan noir pendant l'animation.

0
cdstamper