3

有一个我非常喜欢的图书馆,你可以在这里找到(https://github.com/pixyzehn/MediumMenu)。

本质上,它执行以下操作:

中菜单演示

后面的菜单实际上是一个 UIViewController。如果我们深入研究源代码,我们会发现以下非常重要的代码:

public init(items: [MediumMenuItem], forViewController: UIViewController) {
    self.init()
    self.items = items
    height = screenHeight - 80 // auto-calculate initial height based on screen size
    frame = CGRect(x: 0, y: 0, width: screenWidth, height: height)
    contentController = forViewController
    menuContentTableView = UITableView(frame: frame)
    menuContentTableView?.delegate = self
    menuContentTableView?.dataSource = self
    menuContentTableView?.showsVerticalScrollIndicator = false
    menuContentTableView?.separatorColor = UIColor.clearColor()
    menuContentTableView?.backgroundColor = menuBackgroundColor
    addSubview(menuContentTableView!)

    if panGestureEnable {
        let pan = UIPanGestureRecognizer(target: self, action: #selector(MediumMenu.didPan(_:)))
        contentController?.view.addGestureRecognizer(pan)
    }

    let menuController = UIViewController()
    menuController.view = self

   UIApplication.sharedApplication().delegate?.window??.rootViewController = contentController
   UIApplication.sharedApplication().delegate?.window??.insertSubview(menuController.view, atIndex: 0)
}

前几行并不重要,但最后几行(处理的那些UIApplication.sharedApplication().delegate?.window??是这个库工作的关键,但它们也限制了库。

根据这些行,我们正在制作我们想要菜单的 UIViewController,rootViewController然后我们将菜单视图添加到 0 索引处的窗口(我猜这就是把它放在后面,在contentController)。

图书馆的问题:

该库仅在您想要初始视图控制器上的菜单时才有效。从某种意义上说,只有当 contentController 已经是 rootViewController 时。它实际上会在我的应用程序中为我工作,但我无法回到我原来的 UIViewController 因为它不再在层次结构中。

我有一个场景,我有一个登录视图控制器,当你成功登录时,我会将你转到我想要菜单的 UINavigationController。问题的第一个明显迹象是我收到投诉“警告:尝试在其视图不在窗口层次结构中的 LoginViewController 上呈现 UINavigationController!” 显然,它不在窗口层次结构中,因为我正在重新分配 rootViewController。

我不知道如何解决这个问题。当我想要菜单的 UIViewController 不是初始视图控制器时,有没有办法让这个功能工作?

4

3 回答 3

3

简短的回答是:的。

这可以通过将 a 分配UIViewControllerTransitioningDelegateViewController包含 thelist-menu并实现interactionControllerForPresentation()andinteractionControllerForDismissal()方法来实现。您不必触摸UIWindow(直接)。

你可以只改变现有的这部分library,但从它的外观来看,它只是TableView一个花哨的过渡。您可以自己轻松地实现这一点。

查看 Apple关于交互式转换的API 参考和 Ray Wenderlich 的本教程,以获取动手示例。

于 2016-09-17T08:49:58.817 回答
2

所以很明显你的情况是:

  1. rootViewController=一个UINavigationController
  2. rootViewControllerof是UINavigationControllerLoginController
  3. 当有人登录成功时,navigationController推送(或继续)到 menuController

或者

  1. rootViewController是登录控制器
  2. 当有人登录成功时,它会显示 menuController

所以关键是要得到一个menuController,而不是把它设置到rootViewControllerapp的。

这是我为满足您的要求而进行了一些更改的代码。 https://github.com/Moonsownner/MediumMenu-master

我做了什么:

  1. MediumMenu实际上是一个UIView,我们必须创建一个控制器来包含它,以便进行转换。所以我创建了一个名为MediumMenuController. 你可以看到我将函数showMenu移入MediumMenuController. 因此,如果有人想手动显示菜单,则目标必须是 MediumMenuController 而不是上一个NavigationController。并且MediumMenuController将包含您发送到 init 函数中的业务控制器MediumMenuController
class MediumMenuController: UIViewController {

    let menuView: MediumMenu
    let child: UIViewController

    init(items: [MediumMenuItem], childController: UIViewController){
        self.menuView = MediumMenu(items: items, forViewController: childController)
        self.child = childController
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(menuView)
        addChildViewController(child)
        self.view.addSubview(child.view)
        child.view.frame = UIScreen.mainScreen().bounds
        child.didMoveToParentViewController(self)

    }

    func showMenu() {
        menuView.show()
    }

}
  1. 我删除MediumMenu.

让 menuController = UIViewController(); menuController.view = self UIApplication.sharedApplication().delegate?.window??.rootViewController = contentController UIApplication.sharedApplication().delegate?.window??.insertSubview(menuController.view, atIndex: 0)

并创建一个名为的新控制器,以MediumMenuController向其中添加MediumMenu和其他控制器视图。

可能上面说的不是很清楚。该代码可以向您显示详细信息。祝你好运。

于 2016-09-21T04:06:55.660 回答
2

您可以通过以下步骤来实现它。

(i)LoginViewController成为你的rootViewController.

(ii) 当用户登录成功时,将用户重定向到主屏幕。这是您成功登录后要显示的第一个屏幕。

(iii) 您可以为UIViewControllers要显示菜单的位置创建父类。

(iv) 之后,当你初始化 any 时UIViewController,父类将调用public init(items: [MediumMenuItem], forViewController: UIViewController)方法,你可以用下面的代码替换最后两行。 self.view.insertSubview(menuController.view, atIndex: 0)

(v) 在点击退出按钮时,您可以简单地关闭呈现的视图控制器,因此LoginViewController将始终存在。

希望这可以帮助!

于 2016-09-26T11:35:02.673 回答