Search code examples
tvosswiftui

How to change "MENU" button behaviour to not terminate App


Just right at the start: I don't want to change the user experience from Apple's user experience guidelines, I actually want to bring it back to my App, so here's the problem:

The "MENU" button should go back one level in the navigation hierarchy and terminate the App if there is no level anymore.

My first navigation screen also has an initially hidden full screen view (e.g. a video player). From this first navigation screen the user can go to deeper levels. The "MENU" button has its correct standard behavior.

The deepest navigation level then shows the hidden full screen view. When the user presses "MENU", the navigation should go back to the last level, but instead it terminates the App.

How can I change the behavior of the "MENU" button just for this single view?


Solution

  • It is not difficult to implement this. Just make sure the initial Screen that is displayed to the User is not the root View.

    I will put the stack here. Root View contains two views namely,

    1. VideoContainerView and

    2. MainContainerView.

    VideoContainerView will have a UIViewController, which has menuHandler button listener. This VC displays anotherView on top of RootView on button press.

    MainContainerView will have UIViewController, which doesn't have any menuHandler. MainContainerView is displayed on top of the VideoContainerView.

    STACK

    MainContainerView (Top)

    VideoContainerView

    RootViewController

    RootView -> VideoContainerView (A View containing VideoScreenController) RootView -> MainContainerView (A View containing MainViewController)

    RootView -> VideoContainerView -> VideoScreen (Initial Screen, make sure this is a View Controller displayed on top of that FirstView using ContainerView).

    From the VideoScreenController, Menu button press will display the RootView's MainContainerView which was hidden till now on top of that VideoContainerView.

    On Next Menu button press, the app will go to background, as the MainViewController doesn't handle any menu Button press.

    Never listen to any MenuButton press on the RootView's topView.

    One can easily control the preferred focus flow using,

    override var preferredFocusEnvironments: [UIFocusEnvironment] {
       if topView.isHidden {
          return [VideoContainerView]
       } else {
          return [MainContainerView]
       }
    
    }
    

    Like wise, have preferredFocusEnvironments in every ViewController to handle the initial preferred Focus, so that system is aware which is currently focused.

    The above code, helps the system to know, which view should be focused on launch or on every focus change.