实现随内容自适应高度、满屏后可滚动的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,自动根据子视图计算总高度
拖拽关闭功能实现
- 给
DraggableModalView添加UIPanGestureRecognizer - 在手势回调中:
- 获取拖拽的垂直偏移量,计算模态视图的顶部约束偏移值
- 实时更新
DraggableModalView的顶部约束(或transform),实现跟随拖拽移动的效果 - 当拖拽结束时,判断拖拽距离是否超过阈值(如屏幕高度的1/3):
- 超过阈值:执行模态视图关闭动画(如将视图向下移出屏幕)
- 未超过阈值:执行回弹动画,将视图恢复到当前的自适应高度位置
- 可选:添加拖拽时的阻尼效果,提升交互体验
示例验证
- 示例1:仅添加1个高度50.0px的列表项时,ContentView总高度为50px,低优先级的高度约束生效,DraggableModalView高度被撑至50px,ScrollView无需滚动
- 示例2:添加100个高度50.0px的列表项时,ContentView总高度远超屏幕高度,低优先级约束被打破,DraggableModalView触发高度最大值约束(等于屏幕高度),ScrollView自动允许内容滚动
内容的提问来源于stack exchange,提问作者Matt Beaney
相关产品推荐
相关产品推荐

