You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PopoverViewController展示后动态修改其尺寸(含动画)?

解决Popover中UITableView单元格展开的尺寸适配问题

嘿,我明白你遇到的问题了——你想让popover跟着展开的单元格动态调整尺寸,但之前的preferredContentSize设置没生效对吧?问题出在你重写的preferredContentSize逻辑上,咱们一步步来修复:

问题根源

你之前的preferredContentSize的get方法是固定返回46 * actions.count +64,不管单元格有没有展开,所以哪怕你在点击后设置新值,系统读取的还是原来的固定计算结果,自然不会有尺寸变化。

解决方案步骤

1. 添加状态变量跟踪展开的单元格

首先,咱们需要一个变量记录哪个单元格处于展开状态:

var expandedIndexPath: IndexPath?
// 定义普通单元格和展开后的高度
let normalCellHeight: CGFloat = 46
let expandedCellHeight: CGFloat = 92 // 你可以根据需求调整这个值

2. 动态计算PreferredContentSize

修改preferredContentSize的重写逻辑,根据展开状态计算总高度:

override var preferredContentSize: CGSize {
    get {
        var totalHeight: CGFloat = 64 // 导航栏高度,根据你的实际情况调整
        // 遍历所有条目,累加对应高度
        for row in 0..<actions.count {
            let currentIndexPath = IndexPath(row: row, section: 0)
            totalHeight += (expandedIndexPath == currentIndexPath) ? expandedCellHeight : normalCellHeight
        }
        return CGSize(width: view.frame.width, height: totalHeight)
    }
    set { super.preferredContentSize = newValue }
}

3. 让TableView返回正确的单元格高度

实现heightForRowAt方法,确保单元格能根据展开状态显示对应高度:

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return expandedIndexPath == indexPath ? expandedCellHeight : normalCellHeight
}

4. 处理单元格点击事件,带动画更新尺寸

在didSelectRowAt里切换展开状态,刷新单元格并触发popover尺寸的动画更新:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
    
    // 切换当前行的展开状态
    expandedIndexPath = (expandedIndexPath == indexPath) ? nil : indexPath
    
    // 刷新当前行,展示高度变化动画
    tableView.reloadRows(at: [indexPath], with: .automatic)
    
    // 带动画更新popover尺寸
    UIView.animate(withDuration: 0.3) {
        // 主动触发preferredContentSize的更新
        self.preferredContentSize = self.preferredContentSize
        // 强制containerView布局,让动画更流畅
        self.popoverPresentationController?.containerView?.layoutIfNeeded()
    }
}

额外提示

  • 如果你的导航栏高度不是64,记得调整totalHeight的初始值;
  • 要是需要支持多行展开,只需要把expandedIndexPath改成Set<IndexPath>,遍历的时候判断是否包含即可;
  • 确保你的TableView没有设置固定的rowHeight,或者已经实现了heightForRowAt方法,否则单元格高度不会变化。

这样修改后,点击单元格时,不仅单元格会展开/收起,popover的尺寸也会跟着平滑地调整啦!

内容的提问来源于stack exchange,提问作者Adam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:44:29