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

实现随内容自适应高度、满屏后可滚动的UIScrollView模态框

实现带自适应高度与拖拽关闭的类UISheetPresentationController模态视图

需求概述

实现一个类似UISheetPresentationController的模态视图,具备以下特性:

  • 自适应内容高度:添加内容时视图高度随内容逐步增长
  • 高度上限:达到屏幕高度后停止增长,内部内容支持滚动
  • 全程使用AutoLayout实现布局
  • 支持拖拽手势关闭视图

视图层级结构

- 占满屏幕的ContainerView
  | - DraggableModalView(可拖拽的模态容器)
    | - UIScrollView(内容滚动容器)
      | - ContentView(内容承载容器)
        | - 列表内容(如UIStackView包裹的列表项)

关键AutoLayout约束配置

1. ContainerView

  • 四边约束固定到视图控制器的根视图(或安全区域)

2. DraggableModalView

  • 左、右、底部约束固定到ContainerView的对应边缘
  • 顶部约束设置为DraggableModalView.top >= ContainerView.top(允许视图向上增长,但不超过屏幕顶部)
  • 添加高度最大值约束:DraggableModalView.height <= ContainerView.height(限制视图最高为屏幕高度)
  • 可选:设置初始高度的低优先级约束(如高度>=某个最小高度,避免内容为空时视图消失)

3. UIScrollView

  • 四边约束固定到DraggableModalView的对应边缘
  • 注意:无需设置ScrollView的高度约束,其高度由DraggableModalView决定

4. ContentView

  • 四边约束固定到UIScrollView的contentLayoutGuide
  • 宽度约束:ContentView.width == DraggableModalView.width(确保内容宽度与模态视图一致)
  • 高度约束:添加*低优先级(如250)*的ContentView.height == DraggableModalView.height,当内容总高度小于模态视图最大高度时,ContentView会撑满DraggableModalView,ScrollView无需滚动;当内容高度超过模态视图最大高度时,该低优先级约束会被打破,ContentView高度随内容增长,ScrollView自动开启滚动

5. 列表内容容器(如UIStackView)

  • 四边约束固定到ContentView的对应边缘
  • 列表项添加到该栈视图中,栈视图的axis设置为.vertical,自动根据子视图计算总高度

拖拽关闭功能实现

  1. 给DraggableModalView添加UIPanGestureRecognizer
  2. 在手势回调中:
    • 获取拖拽的垂直偏移量,计算模态视图的顶部约束偏移值
    • 实时更新DraggableModalView的顶部约束(或transform),实现跟随拖拽移动的效果
    • 当拖拽结束时,判断拖拽距离是否超过阈值(如屏幕高度的1/3):
      • 超过阈值:执行模态视图关闭动画(如将视图向下移出屏幕)
      • 未超过阈值:执行回弹动画,将视图恢复到当前的自适应高度位置
  3. 可选:添加拖拽时的阻尼效果,提升交互体验

示例验证

  • 示例1:仅添加1个高度50.0px的列表项时,ContentView总高度为50px,低优先级的高度约束生效,DraggableModalView高度被撑至50px,ScrollView无需滚动
  • 示例2:添加100个高度50.0px的列表项时,ContentView总高度远超屏幕高度,低优先级约束被打破,DraggableModalView触发高度最大值约束(等于屏幕高度),ScrollView自动允许内容滚动

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 14:46:01