返回

iOS开发必备技能:UITableView中cell点击弹出下级列表及高度自适应

IOS

问题描述

在iOS开发中,UITableView 是一个非常常用的控件,用于展示列表数据。然而,有时我们需要实现 cell 点击后弹出下级列表,并且需要支持 cell 高度自适应。本文将详细介绍如何解决这两个问题。

分析原因

1. 实现 cell 点击弹出下级列表

实现 cell 点击弹出下级列表的基本思路是:

  1. 创建一个新的 UITableView
  2. 自定义 UITableViewCell
  3. 实现 UITableViewDelegateUITableViewDataSource 协议。
  4. cell 点击事件中,显示或隐藏下级列表。

2. 实现 cell 高度自适应

实现 cell 高度自适应的基本思路是:

  1. UITableViewCell 中使用自动布局。
  2. 实现 UITableViewDelegateheightForRowAt 方法。
  3. heightForRowAt 方法中,根据 cell 的内容计算 cell 的高度。

解决方案

1. 实现 cell 点击弹出下级列表

步骤 1:创建一个新的 UITableView

let tableView = UITableView(frame: self.view.bounds, style: .plain)
tableView.delegate = self
tableView.dataSource = self
self.view.addSubview(tableView)

步骤 2:自定义 UITableViewCell

class CustomTableViewCell: UITableViewCell {
    let detailTextLabel = UILabel()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupViews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupViews() {
        contentView.addSubview(detailTextLabel)
        detailTextLabel.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            detailTextLabel.topAnchor.constraint(equalTo: contentView.topAnchor),
            detailTextLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            detailTextLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            detailTextLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
        ])
    }
}

步骤 3:实现 UITableViewDelegateUITableViewDataSource 协议

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let cell = tableView.cellForRow(at: indexPath) as? CustomTableViewCell
        cell?.detailTextLabel.text = cell?.detailTextLabel.text == "下级列表" ? nil : "下级列表"
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataSource.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomTableViewCell
        cell.textLabel.text = dataSource[indexPath.row]
        return cell
    }
}

2. 实现 cell 高度自适应

步骤 1:在 UITableViewCell 中使用自动布局

CustomTableViewCell 中设置自动布局约束:

private func setupViews() {
    contentView.addSubview(detailTextLabel)
    detailTextLabel.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        detailTextLabel.topAnchor.constraint(equalTo: contentView.topAnchor),
        detailTextLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
        detailTextLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
        detailTextLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
    ])
}

步骤 2:实现 UITableViewDelegateheightForRowAt 方法

extension ViewController {
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        let text = dataSource[indexPath.row]
        let size = text.size(withAttributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17)])
        return size.height + 20
    }
}

示例代码

以下是完整的示例代码:

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    let tableView = UITableView(frame: self.view.bounds, style: .plain)
    var dataSource = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.delegate = self
        tableView.dataSource = self
        self.view.addSubview(tableView)
    }
    
    // 处理cell点击事件
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let cell = tableView.cellForRow(at: indexPath) as? CustomTableViewCell
        cell?.detailTextLabel.text = cell?.detailTextLabel.text == "下级列表" ? nil : "下级列表"
    }
    
    // 返回cell的数量
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataSource.count
    }
    
    // 创建cell
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomTableViewCell
        cell.textLabel.text = dataSource[indexPath.row]
        return cell
    }
    
    // 返回cell的高度
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        let text = dataSource[indexPath.row]
        let size = text.size(withAttributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17)])
        return size.height + 20
    }
}

class CustomTableViewCell: UITableViewCell {
    let detailTextLabel = UILabel()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupViews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupViews() {
        contentView.addSubview(detailTextLabel)
        detailTextLabel.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            detailTextLabel.topAnchor.constraint(equalTo: contentView.topAnchor),
            detailTextLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            detailTextLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            detailTextLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
        ])
    }
}

总结

本文向您展示了如何在iOS应用程序中使用 UITableView 实现 cell 点击弹出下级列表并实现 cell 高度自适应的功能。您学习了如何创建 UITableView、自定义 UITableViewCell 以及使用委托和数据源方法来处理 cell 的点击事件和高度变化。希望本文对您有所帮助。

相关资源链接