Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected transitions when I add and remove screens from NavigationStack’s path at the same time

I’m using a NavigationStack and I’m dealing with the path programmatically, so I’m always the one appending and removing entries from it to control navigation.

Any time I add or remove views from the path, I get a nice transition that makes sense based on what happened in the path. But things start to get interesting when I remove and add views at the same time:

  • If after I add and remove views the path is larger than before, I get a transition as if I’m navigating forward, which makes a lot of sense.
  • If after I add and remove views the path is smaller than before, I get a transition as if I’m navigating backwards. This isn’t great because sometimes the user is actually navigating forward to a new screen, but they may have done something that caused all the screens behind to become irrelevant (e.g. after logging in), so sometimes it’s weird to get a backward transition. It would be much better if it understood the cases where the tip of the path is a new screen, thus it should be a normal forward transition regardless to what happened to the other screens in the path.
  • And finally, if the path remains with the same size after I add and remove views from it, then I get no transition at all. Even though the path changes, it’s like the implementation is like “well, it still has the same size, so it must be the same” even though that’s not the case.

Is there anything I can do to have more control over the transitions?

like image 300
Fred Porciúncula Avatar asked Oct 24 '25 16:10

Fred Porciúncula


1 Answers

You have little control over the transitions. This question was about disabling the transitions, and even for that you need to rely on UIKit APIs.

That said, once we know how to disable transitions, we can force a "forward" transition. If you want to replace the top of the stack with aNewValue, or if you want to remove the top 2 items, then add aNewValue, you can force a forward transition by doing the following steps:

  1. append aNewValue to the stack
  2. disable animations
  3. remove the last n things in the path
  4. add aNewValue back
  5. enable animations again

e.g.

// this changes the top of the navigation path to "Something Else"
path.append("Something Else")
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1)) {
    UIView.setAnimationsEnabled(false)
    path.removeLast(2)
    path.append("Something Else")
    DispatchQueue.main.async {
        UIView.setAnimationsEnabled(true)
    }
}

I can't think of how you would force a "backward" transition with a type erased NavigationPath, but if your navigation path is a typed array, you can

  1. disable animations
  2. insert the new element as the penultimate item in the path (this doesn't exist on NavigationPaths unfortunately)
  3. enable animations
  4. remove the last element from the path
UIView.setAnimationsEnabled(false)
path.insert("Something Else", at: path.count - 1)
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1)) {
    UIView.setAnimationsEnabled(true)
    path.removeLast()
}
like image 168
Sweeper Avatar answered Oct 26 '25 06:10

Sweeper



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!