【问题标题】:Weird UITableView behavior after expand/collapse the last cell展开/折叠最后一个单元格后的奇怪 UITableView 行为
【发布时间】:2017-02-26 14:03:34
【问题描述】:

我想要实现的是:单击其中的标签时,单元格可以展开/折叠。应该记住单元格大小,以便当用户滚动回单元格时,它应该是以前的大小。我使用自动布局设置单元格,所有视图都分配了高度约束。当用户单击标签时,我通过更改标签的高度约束来更改单元格高度:

func triggerExpandCollapse(_ cell: UITableViewCell) {
    guard let cell  = cell as? ActivityTableViewCell, let indexPath = self.activitiesTableView.indexPath(for: cell) else { return }

    if !self.expandedCellIndex.insert(indexPath.row).inserted {
        self.expandedCellIndex.remove(indexPath.row)
        cell.descLabelHeightConstraint.constant = 60
    }
    else {
        cell.descLabelHeightConstraint.constant = cell.descLabel.intrinsicContentSize.height
    }

    self.activitiesTableView.beginUpdates()
    self.activitiesTableView.endUpdates()
}

并在返回每个单元格之前配置单元格的高度:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: Constants.TableViewCellID.activity, for: indexPath)
    guard let activityCell = cell as? ActivityTableViewCell else {
        return cell
    }

    activityCell.delegate = self
    if self.expandedCellIndex.contains(indexPath.row) {
        activityCell.descLabelHeightConstraint.constant = activityCell.descLabel.intrinsicContentSize.height
    }
    else {
        activityCell.descLabelHeightConstraint.constant = 60
    }
    activityCell.layoutIfNeeded()
    return activityCell
}

我还通过以下方式启用自动布局:

self.activitiesTableView.rowHeight = UITableViewAutomaticDimension
self.activitiesTableView.estimatedRowHeight = 1000

到目前为止,除了最后一个单元格之外,单元格可以正常滚动行为展开/折叠!当我展开最后一个并向上滚动时,activitiesTableView 看起来“跳跃”了一小段距离。详情可以参考video

我现在不知道如何调试。有没有人对此有一些想法?谢谢。

【问题讨论】:

    标签: ios swift uitableview


    【解决方案1】:

    在睡了一觉之后,我做了一些尝试,并想出了一个方法来让单元格展开/折叠,动画和 UITableView 平滑滚动,我所做的可以用以下变化来描述:

    1. 在触发单元格展开/折叠的动画块中包含单元格的layoutIfNeededbeginUpdatesendUpdates。完整版是:

      func triggerExpandCollapse(_ cell: UITableViewCell) {
          guard let cell = cell as? DonationsTableViewCell, let indexPath = self.donationsTableView.indexPath(for: cell) else { return }
      
          if !self.expandedCellsSet.insert(indexPath.row).inserted    // Collapse
          {
              self.expandedCellsSet.remove(indexPath.row)
              cell.projectDescLabelHeightConstraint.constant = 60
          }
          else    // Expand
          {
              cell.projectDescLabelHeightConstraint.constant = cell.projectDescLabel.intrinsicContentSize.height
          }
      
          UIView.animate(withDuration: Constants.TimeDuration.cellExpandCollapse, delay: 0, options: .curveEaseInOut, animations: { 
              cell.layoutIfNeeded()
              self.donationsTableView.beginUpdates()
              self.donationsTableView.endUpdates()
          }, completion: nil)
      }
      
    2. 在这种情况下,滚动指示器会在用户滚动时更改其大小。那是因为estimatedRowHeight 与实际的单元格高度相差太大。我建议实施tableView(_:estimatedHeightForRowAt:) 为每个单元格提供近似高度。注意如果返回值过大,展开/折叠行为会异常

    如果有人有更好的解决方案,我将非常感激!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多