Comment cacher la barre d'onglets avec l'animation dans iOS?

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

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

toute aide serait grandement appréciée: d

52
demandé sur neilco 2014-01-05 19:15:33

11 réponses

j'essaie de garder les animations de vue disponibles pour moi 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");
    }];
}
71
répondu danh 2016-10-12 09:19:04

quand on travaille avec storyboard il est facile de configurer le contrôleur de vue pour cacher la barre de Tab sur push, sur le contrôleur de vue de destination il suffit de sélectionner cette case à cocher:

enter image description here

87
répondu Ben 2015-10-31 07:11:04

comme pour Apple docs, hidesBottomBarWhenPushed propriété de UIViewController, une valeur booléenne, indiquant si la barre d'outils au bas de l'écran est cachée lorsque le contrôleur de vue est poussé sur un contrôleur de navigation.

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

L'approche recommandée pour masquer la barre d'onglets serait comme suit:

    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'aux viewControllers respectifs 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 pousser vers la pile du contrôleur de navigation.

28
répondu ldindu 2014-01-05 16:18:28

version Swift 3.0, en 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
    }
}
  • C'est basé sur l'entrée de Sherwin Zadeh après quelques heures de jeu environ.
  • au lieu de déplacer le tabbar lui-même il déplace le cadre de la vue, ce qui glisse effectivement le tabbar gentiment hors du bas de l'écran mais...
  • ... a l'avantage que le contenu affiché à L'intérieur du UITabbarcontroller prend alors aussi le plein écran!
  • note son également à l'aide de la AssociatedObject de la fonctionnalité de données attachées à la UIView sans sous-classement et donc une extension est possible (extensions de ne pas autoriser stockées les propriétés)

enter image description here

21
répondu HixField 2017-10-22 06:44:12

Version Swift:

@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
répondu Sherwin Zadeh 2016-03-16 01:35:45

essayez de définir le cadre du tabBar en animation. Voir ce tutoriel.

juste être conscient, il est de mauvaise pratique de faire cela, vous devriez mettre show/hide tabBar quand UIViewController push by mettre la propriété hidesBottomBarWhenPushed à YES .

3
répondu gran33 2014-01-05 15:38:29

réécrire 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
répondu Bill Chan 2017-09-20 10:41:52

essayé dans swift 3.0 / iOS10/ Xcode 8:

    self.tabBarController?.tabBar.isHidden = true

je le règle quand mon contrôleur est affiché: (et je le cache 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 d'autres évents peuvent éventuellement déclencher hide /show

1
répondu ingconti 2016-12-11 07:42:18

malheureusement, Je ne peux pas commenter la réponse de HixField parce que je n'ai pas assez de réputation, donc je dois laisser ceci comme une réponse séparée.

sa réponse est l'absence de 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
répondu Bryan Bartow 2017-08-04 21:05:05

basé sur la réponse de HixField et Bil Chan j'ai préparé une version qui fonctionne sur iOS 9 à iOS 11 (Je ne peux pas tester sur d'autres versions en ce moment), et iPhone 4S à iPhone X (testé). Quand vous voulez cacher la barre d'onglets il suffit d'appeler: tabBarController?.set(visible:false, animated: true) , de même si vous voulez montrer appel: tabBarController?.set(visible:true, animated: true) . Vous pouvez aussi trouver ce code dans mon gist: https://gist.github.com/MaciejGad/9a4d1f65dcf382373911c90c548d2713

extension UITabBarController {

func set(visible: Bool, animated: Bool, completion: ((Bool)->Void)? = nil ) {

    guard isVisible() != visible else {
        completion?(true)
        return
    }

    let offsetY = tabBar.frame.size.height
    let duration = (animated ? 0.3 : 0.0)

    let beginTransform:CGAffineTransform
    let endTransform:CGAffineTransform

    if visible {
        beginTransform = CGAffineTransform(translationX: 0, y: offsetY)
        endTransform = CGAffineTransform.identity
    } else {
        beginTransform = CGAffineTransform.identity
        endTransform = CGAffineTransform(translationX: 0, y: offsetY)
    }

    tabBar.transform = beginTransform
    if visible {
        tabBar.isHidden = false
    }

    UIView.animate(withDuration: duration, animations: {
        self.tabBar.transform = endTransform
    }, completion: { compete in
        completion?(compete)
        if !visible {
            self.tabBar.isHidden = true
        }
    })
}

func isVisible() -> Bool {
    return !tabBar.isHidden
}
}
-1
répondu bazyl87 2018-04-30 13:09:15

C'est pour moi: [self.tabBar setHidden:YES];

self est le contrôleur de vue, tabBar est l'id pour la tabBar.

-6
répondu us_david 2014-09-18 06:07:11