web-dev-qa-db-fra.com

Comment masquer la barre d'onglets avec animation dans iOS?

J'ai donc un bouton qui est connecté à un IBAction. Lorsque j'appuie sur le bouton, je souhaite masquer la barre d'onglets de mon application iOS avec une animation. Ce [self setTabBarHidden:hidden animated:NO]; ou ce [self.tabBarController setTabBarHidden:hidden animated:YES]; ne fonctionne pas. Ceci est mon code sans l'animation:

- (IBAction)picture1:(id)sender {
    [self.tabBarController.tabBar setHidden:YES];
}

Toute aide serait grandement appréciée: D

53
b3rge

J'essaie de garder les animations de vue à ma disposition en utilisant la formule suivante:

// pass a param to describe the state change, an animated flag and a completion block matching UIView animations completion 
- (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated completion:(void (^)(BOOL))completion {

    // bail if the current state matches the desired state
    if ([self tabBarIsVisible] == visible) return (completion)? completion(YES) : nil;

    // get a frame calculation ready
    CGRect frame = self.tabBarController.tabBar.frame;
    CGFloat height = frame.size.height;
    CGFloat offsetY = (visible)? -height : height;

    // zero duration means no animation
    CGFloat duration = (animated)? 0.3 : 0.0;

    [UIView animateWithDuration:duration animations:^{
        self.tabBarController.tabBar.frame = CGRectOffset(frame, 0, offsetY);
    } completion:completion];
}

//Getter to know the current state
- (BOOL)tabBarIsVisible {
    return self.tabBarController.tabBar.frame.Origin.y < CGRectGetMaxY(self.view.frame);
}

//An illustration of a call to toggle current state
- (IBAction)pressedButton:(id)sender {
    [self setTabBarVisible:![self tabBarIsVisible] animated:YES completion:^(BOOL finished) {
        NSLog(@"finished");
    }];
}
73
danh

Lorsque vous travaillez avec le scénarimage, il est facile de configurer View Controller pour masquer la barre d’onglet sur Push. Sur le View Controller de destination, cochez cette case:
enter image description here

93
Ben

Selon la documentation Apple, la propriété HidesBottomBarWhenPushed de UIViewController, une valeur booléenne, indique si la barre d'outils en bas de l'écran est masquée lorsque le contrôleur de vue est placé sur un contrôleur de navigation.

La valeur de cette propriété sur le contrôleur de vue le plus élevé détermine si la barre d'outils est visible. 

L’approche recommandée pour masquer la barre d’onglet serait la suivante

    ViewController *viewController = [[ViewController alloc] init];
    viewController.hidesBottomBarWhenPushed = YES;  // This property needs to be set before pushing viewController to the navigationController's stack. 
    [self.navigationController pushViewController:viewController animated:YES];

Cependant, notez que cette approche ne sera appliquée qu'à viewController respectif et ne sera pas propagée à d'autres contrôleurs de vue à moins que vous ne commenciez à définir la même propriété hidesBottomBarWhenPushed dans d'autres viewControllers avant de la placer dans la pile du contrôleur de navigation.

29
ldindu

Swift version 3.0, utilisant une extension:

extension UITabBarController {

    private struct AssociatedKeys {
        // Declare a global var to produce a unique address as the assoc object handle
        static var orgFrameView:     UInt8 = 0
        static var movedFrameView:   UInt8 = 1
    }

    var orgFrameView:CGRect? {
        get { return objc_getAssociatedObject(self, &AssociatedKeys.orgFrameView) as? CGRect }
        set { objc_setAssociatedObject(self, &AssociatedKeys.orgFrameView, newValue, .OBJC_ASSOCIATION_COPY) }
    }

    var movedFrameView:CGRect? {
        get { return objc_getAssociatedObject(self, &AssociatedKeys.movedFrameView) as? CGRect }
        set { objc_setAssociatedObject(self, &AssociatedKeys.movedFrameView, newValue, .OBJC_ASSOCIATION_COPY) }
    }

    override open func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        if let movedFrameView = movedFrameView {
            view.frame = movedFrameView
        }
    }

    func setTabBarVisible(visible:Bool, animated:Bool) {
        //since iOS11 we have to set the background colour to the bar color it seams the navbar seams to get smaller during animation; this visually hides the top empty space...
        view.backgroundColor =  self.tabBar.barTintColor 
        // bail if the current state matches the desired state
        if (tabBarIsVisible() == visible) { return }

        //we should show it
        if visible {
            tabBar.isHidden = false
            UIView.animate(withDuration: animated ? 0.3 : 0.0) {
                //restore form or frames
                self.view.frame = self.orgFrameView!
                //errase the stored locations so that...
                self.orgFrameView = nil
                self.movedFrameView = nil
                //...the layoutIfNeeded() does not move them again!
                self.view.layoutIfNeeded()
            }
        }
            //we should hide it
        else {
            //safe org positions
            orgFrameView   = view.frame
            // get a frame calculation ready
            let offsetY = self.tabBar.frame.size.height
            movedFrameView = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height + offsetY)
            //animate
            UIView.animate(withDuration: animated ? 0.3 : 0.0, animations: {
                self.view.frame = self.movedFrameView!
                self.view.layoutIfNeeded()
            }) {
                (_) in
                self.tabBar.isHidden = true
            }
        }
    }

    func tabBarIsVisible() ->Bool {
        return orgFrameView == nil
    }
}
  • Ceci est basé sur les commentaires de Sherwin Zadeh après quelques heures de jeu.
  • Au lieu de déplacer la barre de tabulation elle-même, elle déplace le cadre de la vue, ce qui la fait glisser joliment hors du bas de l'écran mais ...
  • ... présente l'avantage que le contenu affiché à l'intérieur de UITabbarcontroller occupe également le plein écran!
  • notez également qu’il utilise également la fonctionnalité AssociatedObject pour attacher des données à UIView sans sous-classement; une extension est donc possible (les extensions ne permettent pas les propriétés stockées)

 enter image description here

27
HixField

Version rapide:

@IBAction func tap(sender: AnyObject) {
    setTabBarVisible(!tabBarIsVisible(), animated: true, completion: {_ in })
}


// pass a param to describe the state change, an animated flag and a completion block matching UIView animations completion
func setTabBarVisible(visible: Bool, animated: Bool, completion:(Bool)->Void) {

    // bail if the current state matches the desired state
    if (tabBarIsVisible() == visible) {
        return completion(true)
    }

    // get a frame calculation ready
    let height = tabBarController!.tabBar.frame.size.height
    let offsetY = (visible ? -height : height)

    // zero duration means no animation
    let duration = (animated ? 0.3 : 0.0)

    UIView.animateWithDuration(duration, animations: {
        let frame = self.tabBarController!.tabBar.frame
        self.tabBarController!.tabBar.frame = CGRectOffset(frame, 0, offsetY);
    }, completion:completion)
}

func tabBarIsVisible() -> Bool {
    return tabBarController!.tabBar.frame.Origin.y < CGRectGetMaxY(view.frame)
}
9
Sherwin Zadeh

Essayez de définir le cadre de la barre de tabulation dans l'animation. Voir this tutorial.

Sachez simplement que c’est une mauvaise pratique de le faire, vous devriez définir afficher/masquer la barre de tabulation lorsque UIViewController Push by définira la propriété hidesBottomBarWhenPushed à YES.

3
gran33

Réécrivez la réponse de Sherwin Zadeh dans Swift 4:

/* tab bar hide/show animation */
extension AlbumViewController {
    // pass a param to describe the state change, an animated flag and a completion block matching UIView animations completion
    func setTabBarVisible(visible: Bool, animated: Bool, completion: ((Bool)->Void)? = nil ) {

        // bail if the current state matches the desired state
        if (tabBarIsVisible() == visible) {
            if let completion = completion {
                return completion(true)
            }
            else {
                return
            }
        }

        // get a frame calculation ready
        let height = tabBarController!.tabBar.frame.size.height
        let offsetY = (visible ? -height : height)

        // zero duration means no animation
        let duration = (animated ? kFullScreenAnimationTime : 0.0)

        UIView.animate(withDuration: duration, animations: {
            let frame = self.tabBarController!.tabBar.frame
            self.tabBarController!.tabBar.frame = frame.offsetBy(dx: 0, dy: offsetY)
        }, completion:completion)
    }

    func tabBarIsVisible() -> Bool {
        return tabBarController!.tabBar.frame.Origin.y < view.frame.maxY
    }
}
3
Bill Chan

essayé dans Swift 3.0/iOS10/Xcode 8:

    self.tabBarController?.tabBar.isHidden = true

Je le configure quand mon contrôleur est affiché: (et masqué quand je reviens, après la navigation)

override func viewWillAppear(_ animated: Bool) {

        super.viewWillAppear(animated)
        self.tabBarController?.tabBar.isHidden = false

    }

    override func viewWillDisappear(_ animated: Bool) {
                super.viewWillDisappear(animated)
        self.tabBarController?.tabBar.isHidden = true

    }

BTW: il est préférable d'avoir un drapeau à sauvegarder s'il est affiché ou non, car les autres évents peuvent éventuellement déclencher le masquage/l'affichage

1
ingconti

Malheureusement, je ne peux pas commenter la réponse de HixField parce que je n'ai pas assez de réputation, je dois donc laisser cette réponse séparément.

Sa réponse manque la propriété calculée pour movedFrameView, qui est:

var movedFrameView:CGRect? {
  get { return objc_getAssociatedObject(self, &AssociatedKeys.movedFrameView) as? CGRect }
  set { objc_setAssociatedObject(self, &AssociatedKeys.movedFrameView, newValue, .OBJC_ASSOCIATION_COPY) }
}
1
Bryan Bartow

[Swift4.2]

Vient de créer une extension pour UITabBarController:

import UIKit

extension UITabBarController {
    func setTabBarHidden(_ isHidden: Bool, animated: Bool, completion: (() -> Void)? = nil ) {
        if (tabBar.isHidden == isHidden) {
            completion?()
        }

        if !isHidden {
            tabBar.isHidden = false
        }

        let height = tabBar.frame.size.height
        let offsetY = view.frame.height - (isHidden ? 0 : height)
        let duration = (animated ? 0.25 : 0.0)

        let frame = CGRect(Origin: CGPoint(x: tabBar.frame.minX, y: offsetY), size: tabBar.frame.size)
        UIView.animate(withDuration: duration, animations: {
            self.tabBar.frame = frame
        }) { _ in
            self.tabBar.isHidden = isHidden
            completion?()
        }
    }
}

0
Tai Le