在推送时创建透明导航栏并在弹出

时间:2017-11-24 11:55:47

标签: ios swift uinavigationbar

我正在尝试创建一种效果,即使它接近我想要的效果,但它有一些UI故障,我会解释。

我有,我的家庭导航控制器,我点击一个推动新视图控制器的单元格。

在该视图控制器上viewWillAppear(:)我实现了以下内容:

self.navigationController?.navigationBar.isTranslucent = true
self.navigationController?.navigationBar.backgroundColor = .clear
self.navigationController?.navigationBar.tintColor = .white
self.navigationController?.navigationBar.barTintColor = .clear
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)

通过执行此操作,推送的视图控制器将使其navigationBar透明,并仍然保持按钮可见(这是我想要的),但在推动画上,它在父控制器上显示黑条,因为它也隐藏了父亲的navigationBar

然后在推送的视图控制器viewWillDisappear(_:)上我实现了以下内容:

self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.backgroundColor = .white
self.navigationController?.navigationBar.barTintColor = .white

通过执行此操作,我正在尝试重置父级的navigationBar默认属性,但通过这样做,我在动画期间看到一个黑条,在完成动画之前,这会导致错误的UI / UX。

我在这里做错了什么,或者有更好的方法吗?

谢谢。

2 个答案:

答案 0 :(得分:3)

所以经过一些挖掘和来自@Paulo的一些非常有用的提示后,我已经设法解决了这个问题。

这应该是更容易实现的方式,Apple应该为开发人员提供简单选项,而不是围绕一些黑客进行调整来实现它,但无论如何。

我发现其中一个秘密是我在导航视图控制器时滥用navigationBar.isTranslucent = true / false

为了做到这一点,我在navigationBar中设置了默认的parentViewController属性,这个属性将推送到具有透明navigationBar的视图控制器;我已完成以下操作:

self.navigationController?.navigationBar.backgroundColor = .white
self.navigationController?.navigationBar.barTintColor = .white
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.setBackgroundImage(nil, for: .default)

pushedViewController viewWillAppear(_:)上,您需要实施以下内容:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    guard self.navigationController?.topViewController === self else { return }
    self.transitionCoordinator?.animate(alongsideTransition: { [weak self](context) in
        self?.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
        self?.navigationController?.navigationBar.shadowImage = UIImage()
        self?.navigationController?.navigationBar.backgroundColor = .clear
        self?.navigationController?.navigationBar.barTintColor = .clear
    }, completion: nil)
}

在这里,我设置了所需的navigationBar透明度,但正如您所注意到的,不需要使用isTranslucent属性,我注意到强迫它会在推送动画上显示一些闪烁和奇怪的布局

然后在同一个视图控制器(推送)上,您需要实现您在navigationBar中实现的默认的,所需的parentViewController属性:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    self.transitionCoordinator?.animate(alongsideTransition: { [weak self](context) in
        self?.navigationController?.navigationBar.setBackgroundImage(nil, for: UIBarMetrics.default)
        self?.navigationController?.navigationBar.shadowImage = nil
        self?.navigationController?.navigationBar.backgroundColor = .white
        self?.navigationController?.navigationBar.barTintColor = .white
        }, completion: nil)
}

通过这样做,一切都应该按预期工作。

希望将来帮助某人。

答案 1 :(得分:0)

经过数天的研究,我认为我为此提出了最佳(但远非完美)的解决方案。这样,您可以在发生过渡时自定义导航栏,还可以处理中断的过渡,例如当用户取消弹出时。

    func yourCustomizationMethod(bar: UINavigationBar) {
            // Modify the navigation bar
        }
            
    override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    guard navigationController?.topViewController == self else {
        return
    }
    // The coordinator is nil in some cases
    if let coordinator = transitionCoordinator,
        coordinator.animate(alongsideTransition: { context in
            guard let bar = self.navigationController?.navigationBar else {
                return
            }
            self.yourCustomizationMethod(bar: bar)
        }, completion: nil) {
        return
    } else if let bar = navigationController?.navigationBar {
        yourCustomizationMethod(bar: bar)
    }
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    // Customize only if user transition gets canceled to avoid multiple customizations.
    guard transitionCoordinator?.isCancelled == true,
        let bar = navigationController?.navigationBar else {
        return
    }
    yourCustomizationMethod(bar: bar)
}