0

I want a view to slide up, outside the visible area, when the navigation bar hides.

The view is attached to the safeAreaLayoutGuide:

topConstraint = myView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor)

To slide it out, the constraint is changed:

topConstraint.constant = hidden ? -(myView.frame.height) : 0

This works for iPhone 7 but not for iPhone X. When the navigation is hidden, there is a gap between the view.topAnchor and the view.safeAreaLayoutGuide.topAnchor.

The easiest way would be to attach the view to the bottom anchor of the navigation bar, but the app crashes when trying this:

topConstraint = myView.topAnchor.constraint(equalTo: navigationController!.navigationBar.bottomAnchor)

So how can I slide myView out of the visible area?

Manuel
  • 14,274
  • 6
  • 57
  • 130

2 Answers2

1

The solution was to change the whole constraint, not just the constant:

// Deactivate current constraint
myViewTopConstraint.isActive = false

if #available(iOS 11.0, *) {

    // Set new constraint
    myViewTopConstraint = hidden
        ? myView.bottomAnchor.constraint(equalTo: view.topAnchor)
        : myView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)

} else {
    // Set new constraint
    myViewTopConstraint = hidden
        ? myView.bottomAnchor.constraint(equalTo: view.topAnchor)
        : myView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor)
}

// Activate new constraint
myViewTopConstraint.isActive = true

This layout change is also animateable.

Manuel
  • 14,274
  • 6
  • 57
  • 130
  • Very nice....! you can use a variable for top/bottom anchor and change value of it in conditional flow. And set it at the end/after condtional flow – Krunal Mar 02 '18 at 15:14
  • @Krunal This was actually your answer, credit to you :) – Manuel Mar 02 '18 at 15:21
0

Replace following line

topConstraint = myView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor)

with

if !hidden {

    if #available(iOS 11.0, *) {
        topConstraint = myView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
    } else {
        topConstraint = myView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor)
    }

} else {
     topConstraint = myView.topAnchor.constraint(equalTo: view.topAnchor)
}        
Krunal
  • 77,632
  • 48
  • 245
  • 261
  • If I do that, the view that is supposed to be underneath the navigation bar would be covered by the navigation bar. – Manuel Mar 02 '18 at 14:28
  • Oh... wait a min. – Krunal Mar 02 '18 at 14:29
  • Is such a change in constraint animateable? – Manuel Mar 02 '18 at 14:39
  • Mind that safeArea on iPhone X is smaller then visible area, so if you just put you view over the top of safe area, it still be visible. widnow on the other hand represent all visible area (or window's root controller view) so perhaps it will be much more use to you. – MichaelV Mar 02 '18 at 14:50