Переключение контроллеров представления, используя MDCBottomNavigationBar на iOS - PullRequest
0 голосов
/ 15 мая 2018

Я пытаюсь создать приложение для iOS, которое использует нижнюю навигационную функцию библиотеки Material Design. Я могу получить контроллер представления с нижней панелью навигации для компиляции и отображения, но я не могу добавить другие контроллеры представления и переключаться между ними при нажатии на разные вкладки. У меня все упрощено до двух файлов: один - это мой контроллер представления ввода с нижним элементом навигации, а другой - просто мертвый простой контроллер представления, который я трижды создаю для использования в качестве целей трех вкладок.

В настоящее время моя конкретная ошибка:

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'

Насколько я могу судить, это связано с моими представлениями вкладок. Если я закомментирую строку, которая делает self.viewControllers = [...], она будет загружаться просто отлично, но не переключаться между контроллерами представления.

Я не женат на этом подходе. Если есть другой способ сделать это, я бы хотел это знать. Я не смог многому научиться из документов, но если есть документация для других функций конструирования материалов в виде вкладок, которая работает аналогично, я думаю, что это укажет мне правильное направление.

Вот мой контроллер просмотра записей. Я использовал один из примеров в качестве основы и сильно изменил его.

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

И мои простые контроллеры представления, которые должны быть выключены вкладками:

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 )
    }
}

Ответы [ 3 ]

0 голосов
/ 28 ноября 2018

Вы можете использовать это для переключения контроллера, основной код

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]
    }
}
0 голосов
/ 31 января 2019

Этот код отлично подходит для создания MDCBottomNavBar и переключения между контроллерами представления. Но убедитесь, что вы используете TabBarController.

import UIKit
import MaterialComponents

class TabBarController: UITabBarController, MDCBottomNavigationBarDelegate {

    let bottomNavBar = MDCBottomNavigationBar()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    override func viewWillAppear(_ animated: Bool)
    {
        super.viewWillAppear(animated)
        self.navigationController?.setNavigationBarHidden( true, animated: animated )
    }

    //Initialize Bottom Bar
    init()
    {
        super.init(nibName: nil, bundle: nil)
        commonBottomNavigationTypicalUseSwiftExampleInit()
    }

    @available(*, unavailable)
    required init?(coder aDecoder: NSCoder)
    {
        super.init(coder: aDecoder)
        commonBottomNavigationTypicalUseSwiftExampleInit()
    }

    // Bottom Bar Customization
    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 bottomNavigationBar(_ bottomNavigationBar: MDCBottomNavigationBar, didSelect item: UITabBarItem)
    {
        self.selectedIndex = item.tag
    }

    override func viewWillLayoutSubviews()
    {
        super.viewWillLayoutSubviews()
        layoutBottomNavBar()
    }

    #if swift(>=3.2)
    @available(iOS 11, *)
    override func viewSafeAreaInsetsDidChange()
    {
        super.viewSafeAreaInsetsDidChange()
        layoutBottomNavBar()
    }
    #endif

    // Setting Bottom Bar
    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
    }

}
0 голосов
/ 26 ноября 2018

Просто создайте обычную панель навигации на раскадровке с количеством элементов, которые вы хотите.а затем подключите его к контроллеру, как этот.(здесь я использовал 3 элемента нижней панели. Как и в раскадровке.)

//
//  TabViewController.swift
//  Test Navigation Bar
//
//  Created by ido cohen on 25/11/2018.
//  Copyright © 2018 IdoCohen. All rights reserved.
//

import UIKit
import MaterialComponents.MaterialBottomNavigation_ColorThemer

class TabViewController: UITabBarController, MDCBottomNavigationBarDelegate {
    var colorScheme = MDCSemanticColorScheme()
    let bottomNavBar = MDCBottomNavigationBar()
    override func viewDidLoad() {
        colorScheme.backgroundColor = .white
        view.backgroundColor = colorScheme.backgroundColor
        let tabBarItem1 = UITabBarItem(title: "Home", image: UIImage(named: "Home"), tag: 0)
        let tabBarItem2 = UITabBarItem(title: "Messages", image: UIImage(named: "Email"), tag: 1)
        let tabBarItem3 = UITabBarItem(title: "Favorites", image: UIImage(named: "Cake"), tag: 2)
        tabBarItem3.selectedImage = UIImage(named: "Favorite")
        bottomNavBar.items = [ tabBarItem1, tabBarItem2, tabBarItem3 ]

        bottomNavBar.selectedItem = tabBarItem1
        view.addSubview(bottomNavBar)
        bottomNavBar.delegate = self
        MDCBottomNavigationBarColorThemer.applySemanticColorScheme(colorScheme, toBottomNavigation: bottomNavBar)
    }


    func bottomNavigationBar(_ bottomNavigationBar: MDCBottomNavigationBar, didSelect item: UITabBarItem){
        guard let fromView = selectedViewController?.view, let toView = customizableViewControllers?[item.tag].view else {
            return
        }

        if fromView != toView {
            UIView.transition(from: fromView, to: toView, duration: 0.3, options: [.transitionCrossDissolve], completion: nil)
        }
        self.selectedIndex = item.tag
    }

    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()
    }
}

В этом примере я также использовал переход, если вы хотели бы иметь его.если нет, просто удалите его.

...