如何修复在 tableView 中插入和删除行时淡入淡出动画的奇怪行为?

问题描述 投票:0回答:1

我的 tableView 约束在 ViewController 的顶部、左侧、右侧和底部。
我将 UIButton 放在标题视图中,该标题具有使用插入和删除带有淡入淡出动画的行来扩展和收缩的功能。
但是,当我在第一个和最后一个部分展开而第二个和第三个部分缩小的情况下点击按钮展开第三个部分时,第三个部分的单元格与第三个部分重叠,就像这个视频一样。


我想知道为什么会发生这种情况以及解决方案。 预先感谢。

struct TwoDimentionalData {
  let items: [String]
  var isExpanded: Bool
}

class ViewController: UIViewController {
  
  let headerId = "headerId"
  let cellId = "cellId"
  
  var datas = [TwoDimentionalData]()
  
  @IBOutlet weak var tableView: UITableView! {
    didSet {
      tableView.delegate = self
      tableView.dataSource = self
      tableView.register(CollapsibleTableViewCell.self, forCellReuseIdentifier: cellId)
      tableView.register(CopplasibleTableViewHeader.self, forHeaderFooterViewReuseIdentifier: headerId)
    }
  }
  override func viewDidLoad() {
    super.viewDidLoad()
    datas = [TwoDimentionalData(items: ["Item1-1", "Item1-2"], isExpanded: true),
             TwoDimentionalData(items: ["Item2-1", "Item2-2", "Item2-3"], isExpanded: true),
             TwoDimentionalData(items: ["Item3-1", "Item3-2", "Item3-3", "Item3-4"], isExpanded: true),
             TwoDimentionalData(items: ["Item4-1"], isExpanded: true)
    ]
  }
}

extension ViewController: UITableViewDelegate {
  func numberOfSections(in tableView: UITableView) -> Int {
    return datas.count
  }
  
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return datas[section].isExpanded ? datas[section].items.count : 0
  }
}

extension ViewController: UITableViewDataSource {
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
    cell.backgroundColor = .green
    return cell
  }
  
  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return datas[indexPath.section].isExpanded ? 50 : 0
  }
  
  func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: headerId) as? CopplasibleTableViewHeader
    header?.expandButton.tag = section
    header?.collapsibleTableViewHeaderDelegate = self
    header?.setLayout()
    header?.contentView.backgroundColor = .yellow
    return header
  }
  
  func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 40
  }
  
}

extension ViewController: CollapsibleTableViewHeaderDelegate {
  func didTapExpandButton(tag: Int) {
    let isExpended = datas[tag].isExpanded
    datas[tag].isExpanded = !isExpended
    var indexPaths = [IndexPath]()
    let items = datas[tag].items
    
    for row in items.indices {
      let indexPath = IndexPath(row: row, section: tag)
      indexPaths.append(indexPath)
    }
    
    tableView.performBatchUpdates {
      if isExpended {
        tableView.deleteRows(at: indexPaths, with: .fade)
      } else {
        tableView.insertRows(at: indexPaths, with: .fade)
      }
    }
  }
}

protocol CollapsibleTableViewHeaderDelegate: AnyObject {
  func didTapExpandButton(tag: Int)
}

class CopplasibleTableViewHeader: UITableViewHeaderFooterView {

  weak var collapsibleTableViewHeaderDelegate: CollapsibleTableViewHeaderDelegate?
  
  lazy var expandButton: UIButton = {
    let button = UIButton()
    button.setImage(UIImage(systemName: "chevron.down"), for: .normal)
    button.addTarget(self, action: #selector(handleExpandButton), for: .touchUpInside)
    return button
  }()
  
  @objc private func handleExpandButton(button: UIButton) {
    print("handleExpandButton")
    let tag = button.tag
    collapsibleTableViewHeaderDelegate?.didTapExpandButton(tag: tag)
    
  }
  
  override func prepareForReuse() {
    super.prepareForReuse()
   
  }
  
  func setLayout() {
    addSubview(expandButton)
    expandButton.translatesAutoresizingMaskIntoConstraints = false
    expandButton.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
    expandButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
  }
}
swift tableview
1个回答
0
投票

我通过使用 reloadRows 方法而不是插入/删除行方法解决了这个问题。

首先,将 numberofRowsInSection 更改为以下代码以防止崩溃。

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return datas[section].items.count
  }

在 CollapsibleTableViewHeaderDelegate 内部,

extension ViewController: CollapsibleTableViewHeaderDelegate {
  func didTapExpandButton(tag: Int) {
    let isExpended = datas[tag].isExpanded
    datas[tag].isExpanded = !isExpended
    var indexPaths = [IndexPath]()
    let items = datas[tag].items
    
    for row in items.indices {
      let indexPath = IndexPath(row: row, section: tag)
      indexPaths.append(indexPath)
    }
    
     tableView.performBatchUpdates {
           tableView.reloadRows(at: indexPaths, with: .fade)
       }
  }
}

通过这种方式,我不再获得重叠的单元格,但仍然获得淡入淡出动画。

© www.soinside.com 2019 - 2024. All rights reserved.