记录一次树形分级列表的实现

原创
2019/09/05 17:04
阅读数 296

实现思路

使用 tableView 实现先树形结构(不同的 cell 样式显示不同的等级),当点击 cell 时,判断当前点击的 cell 是否存在下一级,是否已经是打开状态.如果存在下一级,关闭状态,则通过插入 cell 实现点击展开树形图的效果.如果存在下一级且已经展开则通过删除 cell的方式实现树形图的关闭效果.

具体实现

  1. 定义数据结构类型,如下:
class YTTTreeListModel: NSObject {
    
    /**
        你所需要的属性
        var name: String = ""
        var address: String = ""
        var age: Int = -1
        ...
    **/
    
    // 当前节点是否有下一级
    var isShow: Bool = false
    // 当前节点是否展开
    var isOpen: Bool = false
    // 当前的等级
    var level: Int = 0
    // 当前节点的子节点
    var child: [QWMyTeamModel] = []
}
  1. 定义主要的方法(递归算法)
/// 获取 cell 的行数
///
/// - Parameter items: 数据源
/// - Returns: cell 行数
private func getRowsNum(_ items: [YTTTreeListModel]) -> Int {
    var num = 0
    items.forEach { (model) in
        num += 1
        if model.isShow && model.isOpen && model.child.count > 0 {
            num += getRowsNum(model.child)
        }
    }
    return num
}

/// 获取当前 cell 的数据模型
///
/// - Parameters:
///   - items: 数据源
///   - index: 当前位置
/// - Returns: 数据模型
private func getItem(_ items: [YTTTreeListModel], index: inout Int) -> YTTTreeListModel? {

    for item in items {
        if index == 0 {
            return item
        }
        index -= 1
        if item.isShow && item.isOpen && item.child.count > 0 {
            if let model = getItem(item.child, index: &index) {
                return model
            }
        }
    }
    return nil
}

/// 获取需要添加或删除的 cell
///
/// - Parameters:
///   - item: 当前数据模型(点击的 cell)
///   - index: 当前位置
/// - Returns: 需要删除或添加位置
private func getIndexPath(_ item: YTTTreeListModel, index: inout Int) -> [IndexPath] {
    var indexPaths: [IndexPath] = []
    for item in item.child {
        index += 1
        indexPaths.append(IndexPath(row: index, section: 0))
        if item.isShow && item.isOpen && item.child.count > 0 {
            indexPaths.append(contentsOf: getIndexPath(item, index: &index))
        }
    }
    return indexPaths
}
  1. 实现代理方法
// dataArr     private var dataArr: [YTTTreeListModel] = []

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return getRowsNum(dataArr) 
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    var index = indexPath.row
    if let model = getItem(dataArr, index: &index) {
        if model.level == 1 {
            // 返回第一级样式
        } else if model.level == 2 {
            // 返回第二级样式
        }else if model.level == 3 {
            // 返回第三级样式
        }
        ...
    }
    return UITableViewCell()
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    var index = indexPath.row
    if let model = getItem(dataArr, index: &index) {

        if model.isOpen {
            tableView.beginUpdates()
            model.isOpen = false
            var ind = indexPath.row
            tableView.reloadRows(at: [indexPath], with: .none)
            tableView.deleteRows(at: getIndexPath(model, index: &ind), with: .none)
            tableView.endUpdates()
        }else {
            if !model.isShow {
                return
            }
            
            // 存在下一级且子级已经加载直接展开
            if model.isShow == 1 && model.child.count > 0 {
                tableView.beginUpdates()
                model.isOpen = true
                var ind = indexPath.row
                tableView.reloadRows(at: [indexPath], with: .none)
                tableView.insertRows(at: getIndexPath(model, index: &ind), with: .none)
                tableView.endUpdates()
            }else {
            // 存在下一级,但数据未请 求网络请求
            http.globalPOST(url: **, parameters: ["": ""], success: { [weak self] (result) in
                if let models = YTTTreeListModel(dictArray: result) as? [YTTTreeListModel] {
                    model.child = models.compactMap({ (item) -> YTTTreeListModel in
                        item.level = model.level + 1 // 设置等级
                        return item
                    })
                    tableView.beginUpdates()
                    model.isOpen = true
                    var ind = indexPath.row
                    tableView.reloadRows(at: [indexPath], with: .none)
                    if let indexs = self?.getIndexPath(model, index: &ind) {
                        tableView.insertRows(at: indexs, with: .none)
                    }
                    tableView.endUpdates()
                }

            }, fail: {(error) in

            }, isHUD: true)
            }
        }
    }
}
展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部