it-swarm.com.ru

Как скрыть панель вкладок с анимацией в iOS?

Так что у меня есть кнопка, которая связана с IBAction. Когда я нажимаю кнопку, я хочу скрыть панель вкладок в моем приложении для iOS с анимацией. Этот [self setTabBarHidden:hidden animated:NO]; или этот [self.tabBarController setTabBarHidden:hidden animated:YES]; не работает. Это мой код без анимации:

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

Любая помощь будет принята с благодарностью: D

53
b3rge

Я стараюсь держать анимации просмотра доступными для меня, используя следующую формулу:

// 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

При работе с раскадровкой легко настроить View Controller, чтобы скрыть панель вкладок на Push, в целевом View Controller просто установите этот флажок:
enter image description here

93
Ben

Согласно документам Apple, свойство hidesBottomBarWhenPhed объекта UIViewController представляет собой логическое значение, указывающее, скрыта ли панель инструментов в нижней части экрана, когда контроллер представления помещается в контроллер навигации.

Значение этого свойства в самом верхнем контроллере представления определяет, видна ли панель инструментов. 

Рекомендуемый подход к скрытию панели вкладок будет следующим

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

Однако обратите внимание, что этот подход будет применяться только к соответствующему viewController и не будет распространяться на другие контроллеры представления, если только вы не начнете устанавливать то же свойство hidesBottomBarWhenPush в других viewControllers, прежде чем помещать его в стек контроллера навигации.

29
ldindu

Версия Swift 3.0, используя расширение:

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
    }
}
  • Это основано на вкладе Шервина Заде после нескольких часов игры.
  • Вместо того, чтобы перемещать саму панель вкладок, она перемещает рамку представления, это эффективно перемещает панель вкладок из нижней части экрана, но ...
  • ... имеет то преимущество, что содержимое, отображаемое внутри UITabbarcontroller, также занимает весь экран!
  • обратите внимание, что он также использует функциональность AssociatedObject для присоединения данных к UIView без создания подклассов, и, следовательно, расширение возможно (расширения не позволяют сохранять свойства)

 enter image description here

27
HixField

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
Sherwin Zadeh

Попробуйте установить рамку вкладки в анимации. Смотрите это учебник.

Просто имейте в виду, это плохая практика, вы должны установить show/hide tabBar, когда UIViewController Push by устанавливает свойство hidesBottomBarWhenPushed в YES.

3
gran33

Перепишите ответ Шервина Заде в 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

попробовал в Swift 3.0/iOS10/Xcode 8:

    self.tabBarController?.tabBar.isHidden = true

Я установил его, когда отображается мой контроллер: (и Скрыть, когда вернулся, после навигации)

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

    }

Кстати: лучше иметь флаг для сохранения, если он показан или нет, так как другие отверстия могут в конечном итоге вызвать скрытие/показ

1
ingconti

К сожалению, я не могу комментировать ответ HixField, потому что у меня недостаточно репутации, поэтому я должен оставить это как отдельный ответ.

В его ответе отсутствует вычисленное свойство для movedFrameView, а именно:

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]

Только что создал расширение для 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