Swift 3:创建一个带有UICollectionView的自定义TabBar,它可以分割到不同的控制器

时间:2017-02-18 17:24:09

标签: swift swift3 uicollectionview uitabbarcontroller uicollectionviewcell

我在一个有5个单元格的UIView类中创建了一个collectionView。它看起来就像一个TabBar,但是通过collectionView来实现它,我将能够根据我的内容自定义它,对吗?我在appDelegate中设置了这个menuBar,因此它将位于每个视图的顶部。我遇到的问题是在我的collectionView中,我无法在UIView中调用它:

present(viewController), animated: true, completion: nil)

我会在didSelectItemAt方法中调用它,并检查indexPath.item是否= = 0,segue到第一个控制器,但我似乎无法找到解决方法如何执行此操作...这是我的代码。任何帮助都将受到高度赞赏,当然,标记为答案。欢呼声。

App Delegate:

    var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    window = UIWindow(frame: UIScreen.main.bounds)
    window?.makeKeyAndVisible()
    window?.rootViewController = UINavigationController(rootViewController: DummyController())

    let menuBar: MenuBar = {
        let mb = MenuBar()
        return mb
    }()

    window?.addSubview(menuBar)

    _ = menuBar.anchor(nil, left: window?.leftAnchor, bottom: window?.bottomAnchor, right: window?.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 50)

    return true
}

MenuBar类(自定义标签栏):

class MenuBar: UIView, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

lazy var collectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
    cv.backgroundColor = .white
    cv.delegate = self
    cv.dataSource = self
    return cv
}()

let seperatorView: UIView = {
    let view = UIView()
    view.backgroundColor = lightGray
    return view
}()

let imageNames = ["home_selected", "glimpse_selected", "camera_selected", "activity_selected", "profile_selected"]

override init(frame: CGRect) {
    super.init(frame: frame)

    addSubview(collectionView)
    addSubview(seperatorView)

    collectionView.register(MenuCell.self, forCellWithReuseIdentifier: "cellId")

    let selectedIndexPath = IndexPath(item: 0, section: 0)
    collectionView.selectItem(at: selectedIndexPath, animated: false, scrollPosition: .centeredHorizontally)

    _ = collectionView.anchor(self.topAnchor, left: self.leftAnchor, bottom: self.bottomAnchor, right: self.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 0)

    _ = seperatorView.anchor(collectionView.topAnchor, left: collectionView.leftAnchor, bottom: nil, right: collectionView.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 1)

    setupHorizontalBar()
}

var horizontalBarLeftAnchorConstraint: NSLayoutConstraint?

func setupHorizontalBar() {
    let horizontalBarView = UIView()
    horizontalBarView.translatesAutoresizingMaskIntoConstraints = false
    horizontalBarView.backgroundColor = .darkGray
    addSubview(horizontalBarView)

    horizontalBarLeftAnchorConstraint = horizontalBarView.leftAnchor.constraint(equalTo: self.leftAnchor)
    horizontalBarLeftAnchorConstraint?.isActive = true

    horizontalBarView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true

    horizontalBarView.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 1/5).isActive = true
    horizontalBarView.heightAnchor.constraint(equalToConstant: 4).isActive = true
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    if indexPath.item == 1 {
        // segue
    }

    let x = CGFloat(indexPath.item) * frame.width / 5
    horizontalBarLeftAnchorConstraint?.constant = x

    UIView.animate(withDuration: 0.45, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
        self.layoutIfNeeded()

    }, completion: nil)
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 5
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! MenuCell

    cell.imageView.image = UIImage(named: imageNames[indexPath.item])?.withRenderingMode(.alwaysTemplate)

    return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: self.frame.width / 5, height: self.frame.height)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {

    return 0
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

2 个答案:

答案 0 :(得分:0)

您无法从UIView(或任何其他非控制器类)类中呈现UIViewController。但您可以将其添加为子视图。 要呈现或推送UIViewcontroller,您必须从UIViewController类的类中执行此操作。

答案 1 :(得分:0)

您有几个选项,可以使用回电

var cellWithIndexSelected : ((IndexPath) -> Void)?

然后在你的AppDelegate中你可以附加一些功能

menuBar.cellWithIndexSelected = { someIndex in
   window?.rootViewController = UINavigationController(rootViewController: SomeOtherViewController())
}

然后在你的didSelectItemAt方法中你有了这个

if indexPath.item == 1 {
// segue
   cellWithIndexSelected(indexPath)       
}

您可以使用NotificationCenter,也可以使用协议委托模式。

这些可以使用但通常您应该有一个父视图控制器,它包含此标签栏并在您的应用代表之外处理这些演示文稿。

相关问题