实现iOS多层级展开列表


概述

在iOS开发中,经常会遇到需要展示多层级的列表数据的情况。本文将教会你如何实现一个iOS多层级展开列表。我们将使用UITableView作为列表的容器,并利用UITableView的section和row来表示数据的层级关系。同时,我们将使用UITableView的协议方法来处理展开和收起的逻辑。

步骤

步骤一:准备数据

首先,我们需要准备一些测试数据。假设我们的多层级展开列表是一个商品分类的列表,每个分类下面还有一些子分类,最后子分类下面可能还有一些商品。我们可以定义一个数据模型来表示这些分类和商品的信息。

struct Category {
    var name: String
    var subcategories: [Category]
    var products: [String]
}

我们可以使用一个数组来存储所有的分类信息。

var categories: [Category] = []

步骤二:实现展开和收起逻辑

在UITableView的代理方法中,我们可以通过判断section的展开状态来决定是否显示子分类或商品数据。我们可以定义一个数组来保存每个section的展开状态。

var isExpanded: [Bool] = []

然后,在UITableView的代理方法中,我们可以根据isExpanded数组的值来确定每个section是否展开。

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if isExpanded[section] {
        // 如果展开状态为true,则显示子分类或商品的数量
        return categories[section].subcategories.count + categories[section].products.count
    } else {
        // 如果展开状态为false,则不显示子分类或商品
        return 0
    }
}

在点击section的时候,我们可以改变isExpanded数组的值,并调用UITableView的reloadSections方法来刷新展开和收起的效果。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if indexPath.row == 0 {
        // 如果点击的是section header,则改变展开状态并刷新section
        isExpanded[indexPath.section].toggle()
        tableView.reloadSections([indexPath.section], with: .automatic)
    }
}

步骤三:实现UITableViewCell

为了展示分类和商品的信息,我们需要自定义UITableViewCell。我们可以创建一个继承自UITableViewCell的子类,并在其中添加必要的控件和布局。

class CategoryCell: UITableViewCell {
    // 添加展示分类和商品信息的控件
    // ...
}

然后,在UITableView的代理方法中,我们可以根据indexPath来确定每个cell应该展示的数据。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryCell", for: indexPath) as! CategoryCell
    
    if indexPath.row < categories[indexPath.section].subcategories.count {
        // 如果indexPath.row小于子分类的数量,则展示子分类的信息
        let subcategory = categories[indexPath.section].subcategories[indexPath.row]
        cell.textLabel?.text = subcategory.name
    } else {
        // 否则,展示商品的信息
        let productIndex = indexPath.row - categories[indexPath.section].subcategories.count
        let product = categories[indexPath.section].products[productIndex]
        cell.textLabel?.text = product
    }
    
    return cell
}

步骤四:构建界面

最后,我们需要在UIViewController中构建UITableView来展示多层级展开列表。我们可以在Storyboard中拖拽一个UITableView控件,并设置其dataSource和delegate为当前的UIViewController。

class ViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.dataSource = self
        tableView.delegate = self
    }
}

然后,在viewDidLoad方法中,我们可以注册UITableViewCell,并设置UITableView的estimatedRowHeight和rowHeight属性,以便正确计算cell的高度。

override func viewDidLoad() {
    super.viewDidLoad()
    
    tableView.dataSource = self
    tableView.delegate = self
    
    tableView.register(CategoryCell.self, forCellReuseIdentifier: "CategoryCell")
    tableView.estimatedRowHeight = 44
    tableView.rowHeight = UITableView.automaticDimension
}

步骤五:展示数据

最后,我们需要在UITableView的代理方法中返回正确的section数量和每个section的header标题。

func numberOfSections(in tableView: UITableView) -> Int {
    return categories.count
}

func tableView(_