Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent Large Title from Collapsing

The question is simple, how can I prevent a Large Title Navigation Bar from collapse when a scrollview scrolls down?

My navigation must have a large navigation bar at all times... so when a scrollview scroll, the navigation bar shouldn't collapse up, it should stay the same size, how can I do that?

This is how I set the largeTitle preferences

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationItem.hidesBackButton = true
    presenter.expandForSimulatorLayoutIfNeeded()

}


func expandForSimulatorLayoutIfNeeded(){
            if !isExpanded{
        topMenu = TopMenu(frame: expandedNavigationFrame, interactor: interactor)
        oldNavigationBarFrame = navigationBar.frame
        self.navigationBar.addSubview(topMenu)
    }

    if #available(iOS 11.0, *) {
        self.navigationBar.prefersLargeTitles = true
    } else {
        self.navigationBar.frame = expandedNavigationFrame
    }

    let topConstraint = NSLayoutConstraint(item: topMenu, attribute: .top, relatedBy: .equal, toItem: navigationBar, attribute: .top, multiplier: 1, constant: 0)
    let leadingConstraint = NSLayoutConstraint(item: topMenu, attribute: .leading, relatedBy: .equal, toItem: navigationBar, attribute: .leading, multiplier: 1, constant: 0)
    let widthConstraint = NSLayoutConstraint(item: topMenu, attribute: .width, relatedBy: .equal, toItem: self.navigationBar, attribute: .width, multiplier: 1, constant: 0)
    let bottomConstraint = NSLayoutConstraint(item: topMenu, attribute: .bottom, relatedBy: .equal, toItem: navigationBar, attribute: .bottom, multiplier: 1, constant: 0)
    topMenu.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([leadingConstraint, widthConstraint, topConstraint, bottomConstraint])

}
like image 678
Frederico Novack Amaral Pereir Avatar asked Jun 18 '18 18:06

Frederico Novack Amaral Pereir


4 Answers

If you created other views on storyboard, then just call below method on viewDidLoad.

private func preventLargeTitleCollapsing() {
    let dummyView = UIView()
    view.addSubview(dummyView)
    view.sendSubviewToBack(dummyView)
}

My original answer is here.

like image 73
Lal Krishna Avatar answered Sep 20 '22 17:09

Lal Krishna


A workaround i figured out is to add a placeholder view that is not CollectionView/TableView as the very first view in ViewController's base view. This first view will be attached to the top of the safeArea, height can be zero.

Using Storyboard/Xib:

See the below screenshot for this view with constraints

enter image description here

Next add another UIView to serve as a container view for your TableView/CollectionView. This container's top will be attached to bottom of the placeholder view. See the below screenshot for constraints of container view and TableView/CollectionView.

enter image description here

The key here is the first view in the view hierarchy as the navigation bar will check that to set the collapsing effect. Once it does not find it as a CollectionView/TableView, it will not collapse on scrolling.

Programmatically:

If you are setting up view's programmatically then you just need to add a placeholder view at the top.

e.g,

self.view.addSubview(UIView(frame: .zero))
self.view.addSubview(tableView) // or collectionView
like image 19
Kamran Avatar answered Oct 24 '22 01:10

Kamran


If someone arrives here from SwiftUI land, this is a good way to keep your lists in large title mode.

// your content view ...

    var body: some View {
        VStack {
            PreventCollapseView()
            List {
                ForEach(things, id: \.self) { thing in
                    Text(thing.name)
                }
            }
        }
        .navigationBarTitle("All the things")
    }


// end of view


struct PreventCollapseView: View {

    private var mostlyClear = Color(UIColor(white: 0.0, alpha: 0.0005))

    var body: some View {
        Rectangle()
            .fill(mostlyClear)
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 1)
    }
}

like image 5
DogCoffee Avatar answered Oct 24 '22 00:10

DogCoffee


To prevent the large tile nav bar from collapsing simply add a second view to your UIViewController in the viewDidLoad method.

view.addSubview(UIView())

For whatever reason, this breaks the link between your the UIScrollView and the nav bar.

like image 3
aepryus Avatar answered Oct 23 '22 23:10

aepryus