我正在尝试创建一个使用 Material Design 库底部导航功能的 iOS 应用程序。我可以获得一个带有底部导航栏的 View Controller 来编译和显示,但是我无法添加其他 View Controller 并在单击不同选项卡时在它们之间切换。我将所有内容简化为两个文件:一个是带有底部导航内容的入口 View Controller ,另一个只是一个非常简单的 View Controller ,我实例化了 3 次以用作三个选项卡的目标。
目前,我的具体错误是:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'headerViewController does not have a parentViewController. Use [self addChildViewController:appBar.headerViewController]. This warning only appears in DEBUG builds'
据我所知,这与我的选项卡 View 有关。如果我注释掉执行 self.viewControllers = [...] 的行,那么它将正常加载,但不会在 View Controller 之间切换。
我不喜欢这种方法。如果有另一种方法可以做到这一点,我很想知道。我无法从文档中学到很多东西,但如果有其他类似选项卡的 Material Design 功能的文档,它们的工作方式非常相似,我认为这将为我指明正确的方向。
这是我的入口 View Controller 。我以其中一个示例为基础并对其进行了大量修改。
import Foundation
import MaterialComponents
import UIKit
class ICEBottomNavController: UITabBarController, MDCBottomNavigationBarDelegate
{
let appBar = MDCAppBar()
var colorScheme = MDCSemanticColorScheme()
// Create a bottom navigation bar to add to a view.
let bottomNavBar = MDCBottomNavigationBar()
init()
{
super.init(nibName: nil, bundle: nil)
initCommon()
}
@available(*, unavailable)
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
initCommon()
}
func initCommon()
{
self.title = "Bottom Navigation (Swift)"
let statusVC = ICEChildBottomBarViewController( title: "Status", color: UIColor.orange )
let eventsVC = ICEChildBottomBarViewController( title: "Events", color: UIColor.blue )
let contactsVC = ICEChildBottomBarViewController( title: "Contacts", color: UIColor.cyan )
self.viewControllers = [ statusVC, eventsVC, contactsVC ]
self.addChildViewController( appBar.headerViewController )
let color = UIColor(white: 0.2, alpha:1)
appBar.headerViewController.headerView.backgroundColor = color
appBar.navigationBar.tintColor = .white
appBar.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor : UIColor.white]
//appBar.headerViewController.viewControllers
commonBottomNavigationTypicalUseSwiftExampleInit()
}
func bottomNavigationBar(_ bottomNavigationBar: MDCBottomNavigationBar, didSelect item: UITabBarItem)
{
print( "did select item \(item.tag)" )
self.selectedIndex = item.tag
//self.viewControllers?[item.tag].addChildViewController( appBar.headerViewController )
//self.selectedViewController = self.viewControllers?[item.tag]
// self.viewControllers
}
func commonBottomNavigationTypicalUseSwiftExampleInit()
{
view.backgroundColor = .lightGray
view.addSubview(bottomNavBar)
// Always show bottom navigation bar item titles.
bottomNavBar.titleVisibility = .always
// Cluster and center the bottom navigation bar items.
bottomNavBar.alignment = .centered
// Add items to the bottom navigation bar.
let tabBarItem1 = UITabBarItem( title: "Status", image: nil, tag: 0 )
let tabBarItem2 = UITabBarItem( title: "Events", image: nil, tag: 1 )
let tabBarItem3 = UITabBarItem( title: "Contacts", image: nil, tag: 2 )
bottomNavBar.items = [ tabBarItem1, tabBarItem2, tabBarItem3 ]
// Select a bottom navigation bar item.
bottomNavBar.selectedItem = tabBarItem1;
bottomNavBar.delegate = self
}
func layoutBottomNavBar()
{
let size = bottomNavBar.sizeThatFits(view.bounds.size)
let bottomNavBarFrame = CGRect( x: 0,
y: view.bounds.height - size.height,
width: size.width,
height: size.height )
bottomNavBar.frame = bottomNavBarFrame
}
override func viewWillLayoutSubviews()
{
super.viewWillLayoutSubviews()
layoutBottomNavBar()
}
#if swift(>=3.2)
@available(iOS 11, *)
override func viewSafeAreaInsetsDidChange()
{
super.viewSafeAreaInsetsDidChange()
layoutBottomNavBar()
}
#endif
override func viewDidLoad()
{
super.viewDidLoad()
self.selectedIndex = 0
appBar.addSubviewsToParent()
// Theme the bottom navigation bar.
MDCBottomNavigationBarColorThemer.applySemanticColorScheme(colorScheme, toBottomNavigation: bottomNavBar);
}
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden( true, animated: animated )
}
}
// MARK: Catalog by convention
extension ICEBottomNavController
{
class func catalogBreadcrumbs() -> [String] {
return ["Bottom Navigation", "Bottom Navigation (Swift)"]
}
class func catalogIsPrimaryDemo() -> Bool {
return false
}
func catalogShouldHideNavigation() -> Bool {
return true
}
}
我的简单 View Controller 应该被选项卡切换:
import Foundation
import MaterialComponents
import UIKit
class ICEChildBottomBarViewController: UIViewController
{
//let appBar = MDCAppBar()
//var colorScheme = MDCSemanticColorScheme()
var color: UIColor?
init( title: String, color: UIColor )
{
super.init(nibName: nil, bundle: nil)
self.title = title
self.color = color
}
@available(*, unavailable)
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
}
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = self.color
//appBar.addSubviewsToParent()
}
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden( true, animated: animated )
}
}
最佳答案
你可以用这个来切换 Controller ,主要代码
class MaterialTabBarSimple: UITabBarController {
let bottomNavBar = MDCBottomNavigationBar()
// other code copy from Material doc
override func viewDidLoad() {
bottomNavBar = [ your tabBarItems ]
bottomNavBar.delegate = self
self.viewControllers = [ your controllers ]
}
}
extension MaterialTabBarSimple: MDCBottomNavigationBarDelegate {
func bottomNavigationBar(_ bottomNavigationBar: MDCBottomNavigationBar, didSelect item: UITabBarItem) {
print("did select item \(item.tag)")
self.selectedViewController = self.viewControllers![item.tag]
}
}
关于ios - 在 iOS 上使用 MDCBottomNavigationBar 切换 View Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50342566/