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

如何根据内容高度计算自定义BottomSheetController的动画时长?

动态计算BottomSheet动画时长的优化方案

要让不同高度的BottomSheet动画都保持流畅,核心是保证动画的视觉移动速度相对恒定——单纯按高度比例缩放时长会导致矮Sheet闪速弹出、高Sheet拖沓缓慢的问题。结合你的需求,优化实现如下:

优化后的动画代码

internal class PresentAnimation: NSObject, UIViewControllerAnimatedTransitioning {

    // 基础移动速度(单位:pt/秒),可根据手感调整
    private let baseAnimationSpeed: CGFloat = 600
    // 时长边界值,避免极端情况
    private let minDuration: TimeInterval = 0.2
    private let maxDuration: TimeInterval = 0.5

    func transitionDuration(using context: UIViewControllerContextTransitioning?) -> TimeInterval {
        guard let toVC = context?.viewController(forKey: .to) else {
            return minDuration
        }
        // 直接用你设置的preferredContentSize获取准确高度
        let sheetHeight = toVC.preferredContentSize.height
        // 按「移动距离/速度」计算基础时长
        let baseDuration = TimeInterval(sheetHeight / baseAnimationSpeed)
        // 限制时长在合理区间内
        return max(minDuration, min(baseDuration, maxDuration))
    }

    func animateTransition(using context: UIViewControllerContextTransitioning) {
        guard let toView = context.view(forKey: .to),
              let toVC = context.viewController(forKey: .to) else {
            context.completeTransition(false)
            return
        }
        let finalFrame = context.finalFrame(for: toVC)
        // 初始位置:完全隐藏在屏幕底部外
        var startFrame = finalFrame
        startFrame.origin.y = context.containerView.frame.height
        toView.frame = startFrame
        context.containerView.addSubview(toView)
        
        UIView.animate(
            withDuration: transitionDuration(using: context),
            delay: 0,
            usingSpringWithDamping: 1,
            initialSpringVelocity: 0,
            options: .curveEaseInOut,
            animations: {
                toView.frame = finalFrame
            },
            completion: { finished in
                context.completeTransition(finished)
            }
        )
    }
}

关键优化点

  • 速度优先的时长计算:用Sheet高度除以固定速度得到基础时长,确保不同高度的Sheet移动视觉速度一致,流畅度统一。
  • 时长边界限制:通过最小/最大时长,避免矮Sheet动画过快(如高度100pt时,计算时长0.17秒会被拉到0.2秒)、高Sheet动画过慢(如高度400pt时,计算时长0.67秒会被限制到0.5秒)。
  • 精准获取高度:直接读取控制器的preferredContentSize,比取view的frame更准确,避免布局未完成时的尺寸误差。

额外建议

如果你的BottomSheet支持拖拽交互,可以把动画时长范围和拖拽阻尼参数配合调整,让弹出动画和拖拽手感更统一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 13:26:00