2

I have a UICollectionViewController embedded inside a UINavigationController which in turn embedded inside a UITabBarController.

enter image description here

I want to add a UIView to the UICollectionViewController just above the tab bar (shown by red rectangle).

enter image description here

I have the UIView created separately as a nib file.

import UIKit

class BottomView: UIView {

    @IBOutlet var view: UIView!

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

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

    fileprivate func commonInit() {
        Bundle.main.loadNibNamed("BottomView", owner: self, options: nil)
        view.frame = self.frame
        view.autoresizingMask = [.flexibleHeight, .flexibleWidth]
        addSubview(view)
    }
}

And I initialize and add it in the UICollectionViewController like so.

class CollectionViewController: UICollectionViewController {

    fileprivate var bottomView: BottomView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let yPos = view.bounds.height - (tabBarController!.tabBar.frame.size.height + 44)
        bottomView = BottomView(frame: CGRect(x: 0, y: yPos, width: view.bounds.width, height: 44))
        collectionView?.addSubview(bottomView)
    }

    // ...

}

I figured if I substract the combined height of the bottom view plus the tab bar from the entire view's height, I should be able to get the correct y position value. But it's not happening. The view is getting added but way off screen.

How do I calculate the correct y position without hardcoding it?

Example demo project

Isuru
  • 30,617
  • 60
  • 187
  • 303
  • What about creating the BottomView off the UICollectionView? – Rodrigo Morbach Aug 22 '17 at 11:24
  • I'm not sure what you mean.. – Isuru Aug 22 '17 at 11:25
  • You could add the bottom view as the footerView of CollectionView – Aravind A R Aug 22 '17 at 11:26
  • Your BottomView should scroll along with collectionView? – Rodrigo Morbach Aug 22 '17 at 11:30
  • @AravindAR Would it scroll with the collection view? – Isuru Aug 22 '17 at 11:31
  • @RodrigoMorbach No, it should stick to the bottom – Isuru Aug 22 '17 at 11:31
  • What's the reason on of adding your view inside the collection view? what if you let it be a separated view behind the collection view? – Ahmad F Aug 22 '17 at 11:35
  • @AhmadF You mean above the collection view? I tried that too. Added it to the view instead of the collection view but got the same result. – Isuru Aug 22 '17 at 11:37
  • I was thinking about something like this: https://www.dropbox.com/s/gkqa0ysp7xa1j0n/collectionview-uiview.png?dl=0 The green is your BottomView and the blue is your collectionview. They are siblings. – Rodrigo Morbach Aug 22 '17 at 11:38
  • @Isuru try adding the let yPos = view.bounds.height - (tabBarController!.tabBar.frame.size.height + 44) bottomView = BottomView(frame: CGRect(x: 0, y: yPos, width: view.bounds.width, height: 44)) collectionView?.addSubview(bottomView) in the layoutIfNeeded – Aravind A R Aug 22 '17 at 11:45
  • How about the re-usable view ? – Caplin YT Aug 22 '17 at 11:46
  • What are you showing in your screenshot, the red rectangle should represents your custom view, which mean that it is *behind* the collection view; You don't even need to add it to the collection view, just add it to the main view, setup the appropriate constraints and you should be good to go... – Ahmad F Aug 22 '17 at 11:46
  • Use simple UIViewController with UICollectionView and UIView... – iWheelBuy Aug 22 '17 at 11:52
  • call ur bottom view frame in viewdidappear and view?.addSubview(bottomView) – Pavankumar Aug 22 '17 at 12:59

2 Answers2

3

I would suggest adding the BottomView to the UICollectionViewController's view rather than to the collection view itself. This is part of the problem you're having.

You're also trying to set the frame of the BottomView in the viewDidLoad() method using values from view.bounds. The CGRect will return (0.0, 0.0, 0.0, 0.0) at this point because the layout has yet to take place, which is most likely why your positioning is off. Try moving your layout logic to the viewWillLayoutSubviews() method and see if that helps.

A better approach would be by setting auto layout constrains rather than defining a frame manually, this will take a lot of the leg work out for you.

Here's a quick example:

self.bottomView.translatesAutoresizingMaskIntoConstraints = false
self.view.insertSubview(self.bottomView, at: 0)
self.bottomView.bottomAnchor.constraint(equalTo: self.view.layoutMarginsGuide.bottomAnchor).isActive = true
self.bottomView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
self.bottomView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
self.bottomView.heightAnchor.constraint(equalToConstant: 100.0).isActive = true

You can apply autolayout logic in your viewDidLoad() and it should work correctly.

You can find some more information on setting autolayout constraints programatically here:

https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/ProgrammaticallyCreatingConstraints.html

WsCandy
  • 420
  • 3
  • 11
0

Sounds what you want to achieve is exactly the footer view for the UICollectionView.

A footerView is like a view that will stick to the bottom of the collectionView and wont move with the cells.

This will help you add a footer View: https://stackoverflow.com/a/26893334/3165112

Hope that helps!

Mohamad Bachir Sidani
  • 2,077
  • 1
  • 11
  • 17