我如何创建一个包含子菜单的汉堡菜单

Posted

技术标签:

【中文标题】我如何创建一个包含子菜单的汉堡菜单【英文标题】:How can i create a hamburger menu with Sub Menu inside 【发布时间】:2019-09-14 19:32:04 【问题描述】:

我正在开发一个应用程序,其中要求创建一个包含子菜单的汉堡菜单,例如

我尝试了在表格视图单元格等中使用表格的不同方法,但无法创建此菜单。 如果有人有解决方案,请推荐我

【问题讨论】:

尝试使用tableview使用可扩展单元格 您可以混合使用自动布局、约束高度和动画来实现这一点。点击展开,点击再次折叠,通过动画改变高度 我知道这是一个技术问题,但请记住,汉堡菜单不是 ios 中的标准导航概念,其他导航概念更为常见和推荐。例如:Is it OK to use hamburger menus in iOS? 【参考方案1】:

您可以创建这样的项目结构作为您的数据源

struct Item 
    let text: String
    var subItems: [String]?
    var isExpanded = false
    init(_ text: String, items: [String]? = nil) 
        self.text = text
        self.subItems = items
    

用法

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate 

    @IBOutlet var tableView: UITableView!

    private let imgOpen = UIImage(named: "open")
    private let imgClose = UIImage(named: "close")

    private var dataSource = [Item]()

    override func viewDidLoad() 
        super.viewDidLoad()

        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "groupCell")
        self.tableView.dataSource = self
        self.tableView.delegate = self

        self.dataSource.append(Item("HOME"))
        self.dataSource.append(Item("ABOUT US"))
        self.dataSource.append(Item("OUR PROJECTS", items: ["Project-1", "Project-2", "..."]))
        self.dataSource.append(Item("BAHRIA TOWN PHASE 1 - 7"))
        self.dataSource.append(Item("BAHRIA TOWN PHASE 8"))
        self.tableView.reloadData()
    

    func numberOfSections(in tableView: UITableView) -> Int 
        return self.dataSource.count
    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        let item = self.dataSource[section]
        if item.isExpanded, let count = item.subItems?.count 
            return count + 1
        

        return 1
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
            let item = self.dataSource[indexPath.section]

            let cell = tableView.dequeueReusableCell(withIdentifier: "groupCell", for: indexPath)
            var imageView: UIImageView?
            if indexPath.row > 0, let text = item.subItems?[indexPath.row - 1] 
                cell.textLabel?.text = text
             else 
                cell.textLabel?.text = item.text
                if item.subItems != nil 
                    imageView = UIImageView(image: item.isExpanded ? self.imgClose : self.imgOpen)
                
            
            cell.accessoryView = imageView

            return cell
    

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
        let item = self.dataSource[indexPath.section]
        if indexPath.row == 0 && item.subItems != nil 
            self.dataSource[indexPath.section].isExpanded = !item.isExpanded
            let indexSet = IndexSet(integer: indexPath.section)
            tableView.reloadSections(indexSet, with: .automatic)
         else 
            // non-expandable menu item tapped
        
    

【讨论】:

太棒了。很棒的方法。喜欢它。 如果项目不可扩展,我可以得到它的名称吗? dataSource与索引一起使用,如dataSource[index].text,如果您需要子项目的名称,请使用dataSource[index].subItems?[subRowIndex]【参考方案2】:

你应该分开进程。

首先,创建汉堡菜单:为此,我推荐使用这个 3rd 方库:https://github.com/John-Lluch/SWRevealViewController 借助此功能,从屏幕左侧创建侧出菜单非常容易。 最好的事情是你会得到一个负责菜单的 ViewController,这样你就可以轻松地自定义它。

其次,如下所述,您应该使用带有可展开单元格的 tableView。最好的方法是基本上只显示单元格的标题。如果用户点击标题,则显示实际的单元格。 (行高> 0)。有一个关于这个的教程:https://www.youtube.com/watch?v=bSKUYRsMCrM

【讨论】:

【参考方案3】:

->您可以使用以下任何库创建滑动抽屉菜单(汉堡菜单):

1) REFrostedViewController
2) SWRevealViewController or any other

-> 子菜单:在抽屉视图控制器中,您必须添加一个表格视图并实现可展开/可折叠的部分以显示子菜单。您可以按照任何解释展开折叠表格视图部分的教程进行操作。部分教程链接如下:

https://github.com/jeantimex/ios-swift-collapsible-table-section
https://medium.com/@legonaftik/uitableview-with-collapsible-sections-927d726b985c

【讨论】:

【参考方案4】:

第一次关注https://github.com/jonkykong/SideMenu

然后制作 EXPANDABLE Cells:-

您只需要在UITableView(在故事板中)中创建 2 个单元格。第一个单元格用于不可扩展的单元格,第二个单元格用于可扩展单元格。

class SideMenuTableViewController: UITableViewController 

    // MARK:- Constants And Vars
    var isOurProjectCellExpanded = false


class SideMenuTableViewController: UITableViewDataSource, UITableViewDelegate 
      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
            let cell = tableView.dequeueReusableCell(withIdentifier: "simpleCell", for: indexPath) as! SideMenuBasicTableViewCell
            switch indexPath.row 
            case 0:
                cell.itemName.text = "HOME"
                break
            case 1:
                cell.itemName.text = "About Us"
                break
            case 2:
                if(isOurProjectCellExpanded)
                    //expandedCell
                    let cell = tableView.dequeueReusableCell(withIdentifier: "expandedCell", for: indexPath) as! SideMenuBasicTableViewCell
                    cell.itemName.text = "Our Projects"
                    return cell
                else
                    cell.arrowDownImageView.isHidden = false
                    cell.itemName.text = "Our Projects"
                
                break
            case 3:
                cell.itemName.text = "Bahria Town phase 1-7"
                break
            case 4:
                cell.itemName.text = "Bahria Town phase 8"
                break
            default:
                break
            
            return cell
        

     //And in `DidSelectRow` Method
     override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
            if(indexPath.row == 2)
                if(isOurProjectCellExpanded)
                    isOurProjectCellExpanded = false
                    tableView.reloadRows(at: [indexPath], with: .none)
                else
                    isOurProjectCellExpanded = true
                    tableView.reloadRows(at: [indexPath], with: .none)
                
            else if(indexPath.row == 0)
                // Handle it yourself
            else if(indexPath.row == 1)
                // Handle it yourself
            else if(indexPath.row == 3)
                // Handle it yourself
            else if(indexPath.row == 4)
                // Handle it yourself
            
        

    

【讨论】:

以上是关于我如何创建一个包含子菜单的汉堡菜单的主要内容,如果未能解决你的问题,请参考以下文章

汉堡菜单/侧边菜单外观错误

汉堡菜单/侧面菜单出现错误

WPF - 如何使用绑定创建菜单和子菜单

为带有子菜单的移动菜单添加关闭功能

如何使用 Vuetify 创建带有子菜单的菜单?

单击其他菜单项时隐藏当前子菜单