站点图标 Codeun

SwiftUI 中 ScrollView 动态收缩展开顶部视图效果

ScrollView 动态视图效果

这个效果适合个人资料页面,下拉滑动 ScrollView 时,顶部的 NavigationBar 区域向下展开放大,将头像等资料放大展示,上拉滑动后会收起,具体效果如下;

演示效果

https://www.codeun.com/wp-content/uploads/2023/09/2023092715142517.mov
ScrollView 顶部动态效果

实现方式

通过给 ScrollView 添加一个自定义的 HeaderView 头部视图、实现UIViewRepresentable、UIScrollViewDelegate协议,获取 ScrollView 滚动事件来计算 GeometryReader 滚动位置,根据滚动的位置调整整个头部视图的位置和缩放。


完整代码下载


代码示例

以下是 ScrollView 视图部分代码

var size: CGSize // 存储设备屏幕尺寸。
var safeArea: EdgeInsets // 存储设备的安全区域插图。
@State private var offsetY: CGFloat = 0 // 存储ScrollView的Y偏移量。

var body: some View {
    ScrollViewReader { scrollProxy in
        ScrollView(.vertical, showsIndicators: false) {
            VStack(spacing: 0) {
                // 头部视图
                HeaderView()
                    .zIndex(999) // 设置层次,保证HeaderView总是在顶层。
                
                // 卡片样本视图
                SampleCardsView()
            }
            .id("SCROLLVIEW")
            .background {
                // ScrollDetector监测滚动事件
                ScrollDetector { offset in
                    offsetY = -offset // 更新偏移量
                } onDraggingEnd: { offset, velocity in
                    let headerHeight = (size.height * 0.3) + safeArea.top
                    let minimumHeaderHeight = 65 + safeArea.top
                    
                    let targetEnd = offset + (velocity * 45)
                    
                    // 控制滚动结束后的位置
                    if targetEnd < (headerHeight - minimumHeaderHeight) && targetEnd > 0 {
                        withAnimation(.interactiveSpring(response: 0.55, dampingFraction: 0.65, blendDuration: 0.65)) {
                            scrollProxy.scrollTo("SCROLLVIEW", anchor: .top)
                        }
                    }
                }
            }
        }
    }
}

退出移动版