如何更改 "MENU" 按钮行为以不终止应用程序

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

刚开始:我不想改变Apple用户体验指南的用户体验,我实际上想把它带回我的应用程序,所以问题来了:

"MENU" 按钮应该返回导航层次结构中的一个级别,如果没有级别,则终止应用程序。

我的第一个导航屏幕也有一个最初隐藏的全屏视图(例如视频播放器)。从第一个导航屏幕,用户可以进入更深层次。 "MENU" 按钮有其正确的标准行为。

最深的导航级别然后显示隐藏的全屏视图。当用户按下 "MENU" 时,导航应该返回到最后一级,但它会终止应用程序。

如何仅针对此单个视图更改 "MENU" 按钮的行为?

真正导致您的应用程序退出的是,如果按下菜单按钮的 pressesEnded:withEvent: 一直沿着响应链向上到达 UIApplication。因此,如果您阻止这种情况发生,应用程序将不会退出。

有两种方法可以做到这一点:响应者链中的某个人需要覆盖该方法并且调用super,或者响应者链中的某个人需要有一个识别按钮按下的手势识别器。

UINavigationController,例如,使用后者。如果导航堆栈位于其根部,它也会禁用手势;这样,尝试弹出最后一个视图控制器实际上会退出应用程序。

实现起来并不难。只需确保显示给用户的初始屏幕不是根视图。

我会把堆栈放在这里。 根视图包含两个视图,即

  1. VideoContainerView 和

  2. MainContainerView。

VideoContainerView 将有一个 UIViewController,它有 menuHandler 按钮侦听器。此 VC 在按下按钮时在 RootView 顶部显示另一个视图。

MainContainerView 将有 UIViewController,它没有任何 menuHandler。 MainContainerView 显示在 VideoContainerView 之上。

堆栈

MainContainerView(顶部)

VideoContainerView

根目录ViewController

RootView -> VideoContainerView(包含 VideoScreenController 的视图) RootView -> MainContainerView(包含 MainViewController 的视图)

RootView -> VideoContainerView -> VideoScreen(初始屏幕,确保这是使用 ContainerView 显示在 FirstView 之上的视图控制器)。

在 VideoScreenController 中,按下菜单按钮 将显示 RootView 的 MainContainerView,它一直隐藏在该 VideoContainerView 的顶部。

按下“下一个菜单”按钮时,应用程序将进入后台,因为“主”ViewController 不处理任何菜单按钮按下。

永远不要听 RootView 的 topView 上的任何 MenuButton 按下。

可以使用

轻松控制首选焦点流
override var preferredFocusEnvironments: [UIFocusEnvironment] {
   if topView.isHidden {
      return [VideoContainerView]
   } else {
      return [MainContainerView]
   }

}

同样,在每个 ViewController 中都有 preferredFocusEnvironments 来处理初始首选焦点,以便系统知道当前焦点是什么。

上面的代码,帮助系统知道哪个视图应该在启动时或在每次焦点更改时聚焦。