web-dev-qa-db-fra.com

Comment masquer/afficher une barre de tabulation lorsque vous appuyez sur Swift dans iOS8

J'essaie d'imiter le nouveau hidesBarsOnTap du contrôleur UINavigation avec une barre d'onglets. J'ai vu de nombreuses réponses à cette question qui suggèrent de définir la hidesBottomBarWhenPushed sur un viewController qui ne le cache que complètement et non lorsqu'il est exploité.

 @IBAction func tapped(sender: AnyObject) {

    // what goes here to show/hide the tabBar ???


}

merci d'avance

EDIT: selon la suggestion ci-dessous j'ai essayé

self.tabBarController?.tabBar.hidden = true

ce qui cache effectivement le tabBar (bascule vrai/faux du robinet), mais sans animation. Je vais poser cette question séparément.

23
Michael Campsall

Après beaucoup de recherches et d'essais de différentes méthodes pour masquer/afficher gracieusement l'UITabBar avec Swift, j'ai pu prendre cette excellente solution de danh et la convertir en Swift: 

func setTabBarVisible(visible:Bool, animated:Bool) {

//* This cannot be called before viewDidLayoutSubviews(), because the frame is not set before this time

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

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

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

    //  animate the tabBar
    if frame != nil {
        UIView.animateWithDuration(duration) {
            self.tabBarController?.tabBar.frame = CGRectOffset(frame!, 0, offsetY!)
            return
        }
    }
}

func tabBarIsVisible() ->Bool {
    return self.tabBarController?.tabBar.frame.Origin.y < CGRectGetMaxY(self.view.frame)
}

// Call the function from tap gesture recognizer added to your view (or button)

@IBAction func tapped(sender: AnyObject) {
    setTabBarVisible(!tabBarIsVisible(), animated: true)
}
47
Michael Campsall

J'ai adoré la réponse de Michael Campsall. Voici le même code que l'extension, si quelqu'un est intéressé:

Swift 2.3

extension UITabBarController {

    func setTabBarVisible(visible:Bool, animated:Bool) {

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

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

        // animate the tabBar
        UIView.animateWithDuration(animated ? 0.3 : 0.0) {
            self.tabBar.frame = CGRectOffset(frame, 0, offsetY)
            self.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height + offsetY)
            self.view.setNeedsDisplay()
            self.view.layoutIfNeeded()
        }
    }

    func tabBarIsVisible() ->Bool {
        return self.tabBar.frame.Origin.y < CGRectGetMaxY(self.view.frame)
    }
}

Swift 3

extension UIViewController {

    func setTabBarVisible(visible: Bool, animated: Bool) {
        //* This cannot be called before viewDidLayoutSubviews(), because the frame is not set before this time

        // bail if the current state matches the desired state
        if (isTabBarVisible == visible) { return }

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

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

        //  animate the tabBar
        if frame != nil {
            UIView.animate(withDuration: duration) {
                self.tabBarController?.tabBar.frame = frame!.offsetBy(dx: 0, dy: offsetY!)
                return
            }
        }
    }

    var isTabBarVisible: Bool {
        return (self.tabBarController?.tabBar.frame.Origin.y ?? 0) < self.view.frame.maxY
    }
}
25
Kie

J'ai dû adapter un peu la réponse acceptée à cette question. Il cachait le bar mais ma vue ne se dimensionnait pas correctement et il me restait un espace en bas. 

Le code suivant anime correctement le masquage de la barre d'onglets lors du redimensionnement de la vue pour éviter ce problème.

Mise à jour pour Swift 3 (maintenant avec un code moins laid)

func setTabBarVisible(visible: Bool, animated: Bool) {
    guard let frame = self.tabBarController?.tabBar.frame else { return }
    let height = frame.size.height
    let offsetY = (visible ? -height : height)
    let duration: TimeInterval = (animated ? 0.3 : 0.0)

    UIView.animate(withDuration: duration,
                   delay: 0.0,
                   options: UIViewAnimationOptions.curveEaseIn,
                   animations: { [weak self] () -> Void in
                    guard let weakSelf = self else { return }
                    weakSelf.tabBarController?.tabBar.frame = frame.offsetBy(dx: 0, dy: offsetY)
                    weakSelf.view.frame = CGRect(x: 0, y: 0, width: weakSelf.view.frame.width, height: weakSelf.view.frame.height + offsetY)
                    weakSelf.view.setNeedsDisplay()
                    weakSelf.view.layoutIfNeeded()
    })
}

func handleTap(recognizer: UITapGestureRecognizer) {
    setTabBarVisible(visible: !tabBarIsVisible(), animated: true)
}

func tabBarIsVisible() -> Bool {
    guard let tabBar = tabBarController?.tabBar else { return false }
    return tabBar.frame.Origin.y < UIScreen.main.bounds.height
}

Ancienne version Swift 2

func setTabBarVisible(visible: Bool, animated: Bool) {
    // hide tab bar
    let frame = self.tabBarController?.tabBar.frame
    let height = frame?.size.height
    var offsetY = (visible ? -height! : height)
    println ("offsetY = \(offsetY)")

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

    // animate tabBar
    if frame != nil {
        UIView.animateWithDuration(duration) {
            self.tabBarController?.tabBar.frame = CGRectOffset(frame!, 0, offsetY!)
            self.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height + offsetY!)
            self.view.setNeedsDisplay()
            self.view.layoutIfNeeded()
            return
        }
    }
}

@IBAction func handleTap(recognizer: UITapGestureRecognizer) {
    setTabBarVisible(!tabBarIsVisible(), animated: true)
}

func tabBarIsVisible() -> Bool {
    return self.tabBarController?.tabBar.frame.Origin.y < UIScreen.mainScreen().bounds.height
}
13
allocate

Vous pouvez simplement ajouter cette ligne à ViewDidLoad () dans Swift:

self.tabBarController?.tabBar.hidden = true
7
MichelRobico

J'utilise tabBar.hidden = YES dans ObjC pour masquer la barre d'onglets dans certains cas. Je n'ai cependant pas essayé de le relier à un événement tap.

2
Mike Taverne

Le code est correct mais lorsque vous utilisez presentViewController, tabBarIsVisible() ne fonctionne pas. Pour garder UITabBarController toujours caché, utilisez seulement cette partie:

extension UITabBarController {
    func setTabBarVisible(visible:Bool, animated:Bool) {
        let frame = self.tabBar.frame
        let height = frame.size.height
        let offsetY = (visible ? -height : height)
        UIView.animateWithDuration(animated ? 0.3 : 0.0) {
            self.tabBar.frame = CGRectOffset(frame, 0, offsetY)
            self.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height + offsetY)
            self.view.setNeedsDisplay()
            self.view.layoutIfNeeded()
        }
    }
}
2
fatihyildizhan

Swift 3 version: 

func setTabBarVisible(visible:Bool, animated:Bool) {

    //* This cannot be called before viewDidLayoutSubviews(), because the frame is not set before this time

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

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

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

    //  animate the tabBar
    if frame != nil {
        UIView.animate(withDuration: duration) {

            self.tabBarController?.tabBar.frame = (self.tabBarController?.tabBar.frame.offsetBy(dx: 0, dy: offsetY!))!
            return
        }
    }
}

func tabBarIsVisible() ->Bool {
    return (self.tabBarController?.tabBar.frame.Origin.y)! < self.view.frame.midY
}
1
Okan Yücel

Pour Swift 4 , et animation + masquage par en plaçant TabBar hors de la vue :

if let tabBar = tabBarController?.tabBar,
   let y = tabBar.frame.Origin.y + tabBar.frame.height {
   UIView.animate(withDuration: 0.2) {
     tabBar.frame = CGRect(Origin: CGPoint(x: tabBar.frame.Origin.x, y: y), size: tabBar.frame.size)
   }
}
0
traneHead