Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/93.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何将滑出/汉堡菜单合并到现有的选项卡栏控制器_Ios_Uitabbarcontroller_Swift4 - Fatal编程技术网

Ios 如何将滑出/汉堡菜单合并到现有的选项卡栏控制器

Ios 如何将滑出/汉堡菜单合并到现有的选项卡栏控制器,ios,uitabbarcontroller,swift4,Ios,Uitabbarcontroller,Swift4,所以我想创建一个滑出菜单。我希望在触摸选项卡栏项目/按钮时,菜单滑出。 到目前为止,我已经创建了一个带有4个不同选项卡栏按钮的选项卡视图控制器。每个按钮都指向不同的视图控制器,每个视图控制器都已分离到各自的故事板中 我尝试将侧菜单的UIViewController添加到已建立为UIAbbarController的类中,但出现错误: 从类“UITabBarController”和“UIViewController”的多重继承 有办法解决这个问题吗 我感谢所有的帮助不要使用UITabBarContr

所以我想创建一个滑出菜单。我希望在触摸选项卡栏项目/按钮时,菜单滑出。 到目前为止,我已经创建了一个带有4个不同选项卡栏按钮的选项卡视图控制器。每个按钮都指向不同的视图控制器,每个视图控制器都已分离到各自的故事板中

我尝试将侧菜单的UIViewController添加到已建立为UIAbbarController的类中,但出现错误:

从类“UITabBarController”和“UIViewController”的多重继承

有办法解决这个问题吗


我感谢所有的帮助

不要使用UITabBarController,使用一个视图控制器和按钮操作来管理选项卡控件。

应用程序往往有一个顶级容器,如
选项卡栏控制器
,不能嵌入视图中。这里的方法是将主体和左菜单分别包装在
容器视图中。现在,这两个元素都可以安排在包装器
视图控制器

一个
滚动视图
用于通过移动左菜单开/关屏幕来模拟打开和关闭菜单

包含视图控制器 将
视图控制器
放到情节提要上。这是您进入应用程序的入口点。 选中
为初始视图控制器的复选框。
将
模拟大小
固定
更改为
自由形式
。将宽度设置为568,以便我们可以并排安装菜单和选项卡栏。 创建新的Swift文件并将此视图控制器的类设置为ContainerVC

import UIKit
class ContainerVC : UIViewController {
}
滚动视图 在容器视图控制器内,放入一个
滚动视图
,并在各个方向添加约束

选中启用滚动的
。这允许您平移屏幕以滑动菜单。如果应用程序使用水平滚动元素,则可能需要禁用此功能

选中启用分页的
框。这会将菜单捕捉到打开或关闭状态

取消选中
反弹
框。您确实不想滚动到选项卡栏控制器的右边缘

将IB插座连接至ContainerVC:

@IBOutlet weak var scrollView: UIScrollView!
class ContainerVC : UIViewController {

    // This value matches the left menu's width in the Storyboard
    let leftMenuWidth:CGFloat = 260

    // Need a handle to the scrollView to open and close the menu
    @IBOutlet weak var scrollView: UIScrollView!

    override func viewDidLoad() {

        // Initially close menu programmatically.  This needs to be done on the main thread initially in order to work.
        DispatchQueue.main.async() {
            self.closeMenu(animated: false)
        }

        // Tab bar controller's child pages have a top-left button toggles the menu
        NotificationCenter.default.addObserver(self, selector: #selector(ContainerVC.toggleMenu), name: NSNotification.Name(rawValue: "toggleMenu"), object: nil)

        NotificationCenter.default.addObserver(self, selector: #selector(ContainerVC.closeMenuViaNotification), name: NSNotification.Name(rawValue: "closeMenuViaNotification"), object: nil)

        // Close the menu when the device rotates
        NotificationCenter.default.addObserver(self, selector: #selector(ContainerVC.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

        // LeftMenu sends openModalWindow
        NotificationCenter.default.addObserver(self, selector: #selector(ContainerVC.openModalWindow), name: NSNotification.Name(rawValue: "openModalWindow"), object: nil)

    }

    // Cleanup notifications added in viewDidLoad
    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    @objc func openModalWindow() {
        performSegue(withIdentifier: "openModalWindow", sender: nil)
    }

    @objc func toggleMenu() {
        scrollView.contentOffset.x == 0  ? closeMenu() : openMenu()
    }

    // This wrapper function is necessary because closeMenu params do not match up with Notification
    @objc func closeMenuViaNotification(){
        closeMenu()
    }

    // Use scrollview content offset-x to slide the menu.
    func closeMenu(animated:Bool = true){
        scrollView.setContentOffset(CGPoint(x: leftMenuWidth, y: 0), animated: animated)
    }

    // Open is the natural state of the menu because of how the storyboard is setup.
    func openMenu(){
        print("opening menu")
        scrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
    }

    @objc func rotated(){
        if UIDeviceOrientationIsLandscape(UIDevice.current.orientation) {
            DispatchQueue.main.async() {
                print("closing menu on rotate")
                self.closeMenu()
            }
        }
    }
}

extension ContainerVC : UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        print("scrollView.contentOffset.x:: \(scrollView.contentOffset.x)")
    }

    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        scrollView.isPagingEnabled = true
    }

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        scrollView.isPagingEnabled = false
    }
}
左容器 左边的容器保存着菜单,并不是整个屏幕的宽度

容器视图
拖动到
滚动视图的左侧

将顶部、左侧和右侧的约束添加到包含的
滚动视图

硬编码宽度为260

使用ContainerVC的嵌入视图为等高添加约束。注意:不要将高度约束到滚动视图。 删除
容器视图附带的嵌入式
视图控制器

将一个新的
表视图控制器
(根据需要的任何视图)放到情节提要上,并使用嵌入式segue进行连接

右容器 右边的容器包含应用程序的主体,即
选项卡栏控制器

将第二个
容器视图
拖动到
滚动视图的右侧

向包含顶部、右侧和底部的
滚动视图添加约束。水平连接到先前创建的左侧容器视图

等高
等宽
约束到ContainerVC的嵌入视图

注意:不要将这些限制到滚动视图

再次删除随
容器视图免费提供的嵌入式视图控制器。相反,创建一个
embed
segue到
选项卡栏控制器

要在两个容器之间创建一个小的可视分隔,请在右侧容器中添加一个
运行时属性
。添加
layer.shadowOpacity
,数字为
0.8

标签 将每个选项卡嵌入
导航控制器
。这样做可以为您提供一个免费的
导航栏

栏按钮项
拖动到每个
导航栏的左上角

iAction
连接到每个控制器。它们将向曾祖父发出
通知
,以切换菜单

@IBAction func toggleMenu(sender: AnyObject) {
  NotificationCenter.default().post(name: Notification.Name("toggleMenu"), object: nil)
}
最后将以下代码添加到ContainerVC中:

@IBOutlet weak var scrollView: UIScrollView!
class ContainerVC : UIViewController {

    // This value matches the left menu's width in the Storyboard
    let leftMenuWidth:CGFloat = 260

    // Need a handle to the scrollView to open and close the menu
    @IBOutlet weak var scrollView: UIScrollView!

    override func viewDidLoad() {

        // Initially close menu programmatically.  This needs to be done on the main thread initially in order to work.
        DispatchQueue.main.async() {
            self.closeMenu(animated: false)
        }

        // Tab bar controller's child pages have a top-left button toggles the menu
        NotificationCenter.default.addObserver(self, selector: #selector(ContainerVC.toggleMenu), name: NSNotification.Name(rawValue: "toggleMenu"), object: nil)

        NotificationCenter.default.addObserver(self, selector: #selector(ContainerVC.closeMenuViaNotification), name: NSNotification.Name(rawValue: "closeMenuViaNotification"), object: nil)

        // Close the menu when the device rotates
        NotificationCenter.default.addObserver(self, selector: #selector(ContainerVC.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

        // LeftMenu sends openModalWindow
        NotificationCenter.default.addObserver(self, selector: #selector(ContainerVC.openModalWindow), name: NSNotification.Name(rawValue: "openModalWindow"), object: nil)

    }

    // Cleanup notifications added in viewDidLoad
    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    @objc func openModalWindow() {
        performSegue(withIdentifier: "openModalWindow", sender: nil)
    }

    @objc func toggleMenu() {
        scrollView.contentOffset.x == 0  ? closeMenu() : openMenu()
    }

    // This wrapper function is necessary because closeMenu params do not match up with Notification
    @objc func closeMenuViaNotification(){
        closeMenu()
    }

    // Use scrollview content offset-x to slide the menu.
    func closeMenu(animated:Bool = true){
        scrollView.setContentOffset(CGPoint(x: leftMenuWidth, y: 0), animated: animated)
    }

    // Open is the natural state of the menu because of how the storyboard is setup.
    func openMenu(){
        print("opening menu")
        scrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
    }

    @objc func rotated(){
        if UIDeviceOrientationIsLandscape(UIDevice.current.orientation) {
            DispatchQueue.main.async() {
                print("closing menu on rotate")
                self.closeMenu()
            }
        }
    }
}

extension ContainerVC : UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        print("scrollView.contentOffset.x:: \(scrollView.contentOffset.x)")
    }

    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        scrollView.isPagingEnabled = true
    }

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        scrollView.isPagingEnabled = false
    }
}
该代码实现以下功能:

  • 收听“切换菜单”通知
  • 通过基于 当前contentOffset.x
  • 通过更改contentOffset-x打开和关闭菜单

希望您有一个简单的左滑出菜单,可以在其上构建应用程序的其余部分。

@Ajo-answer是正确的。在容器视图中嵌入hamburger和tabbar

你可以从下面的链接找到完整的源代码

我还发现了一个详细的教程

将初始视图控制器用作容器视图。 使用滑入/滑出通知


请显示您的问题代码。PS:UIAbbarController已经从UIViewController继承。我使用故事板而不是代码创建了选项卡栏,这可能不是一个好主意,所以我应该放弃UIAbbarController,使用视图控制器以编程方式创建选项卡栏?