我正在尝试创建一种效果,即使它接近我想要的效果,但它有一些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。
我在这里做错了什么,或者有更好的方法吗?
谢谢。
答案 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)
}