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

SwiftUI中如何防止ScrollView内视图滑出屏幕(固定顶部栏)

实现滚动时固定顶部栏的SwiftUI方案

要实现你需要的效果——让三个矩形组成的栏滚动到屏幕顶部后固定,同时允许圆形视图先固定再滑出、下方列表正常滚动,可以通过GeometryReader监听滚动偏移量,结合视图叠加和偏移控制来实现。

核心思路

  • 用GeometryReader获取滚动视图的实时偏移量,判断目标视图是否到达屏幕顶部
  • 将需要固定的视图(矩形栏、可选的圆形)放在ScrollView的叠加层中,根据偏移量控制其位置
  • 在ScrollView内保留对应占位视图,避免内容滚动时出现跳动

完整实现代码

import SwiftUI

struct ContentView: View {
    // 记录滚动偏移量
    @State private var scrollOffset: CGFloat = 0
    // 记录圆形视图的高度,用于计算固定时机
    @State private var circleHeight: CGFloat = 0
    // 记录矩形栏的高度,用于计算占位高度
    @State private var barHeight: CGFloat = 0
    
    var body: some View {
        GeometryReader { proxy in
            let screenTop = proxy.safeAreaInsets.top
            
            ScrollView {
                LazyVStack(spacing: 0) {
                    // 圆形视图的占位,用于占据空间
                    Color.clear
                        .frame(height: circleHeight)
                    
                    // 矩形栏的占位,用于占据空间
                    Color.clear
                        .frame(height: barHeight)
                    
                    // 下方重复列表
                    ForEach(0..<20) { index in
                        VStack {
                            Image(systemName: "globe")
                                .imageScale(.large)
                                .foregroundColor(.accentColor)
                            Text("Hello, world!")
                        }
                        .padding()
                    }
                }
                .padding()
                .background(
                    // 监听滚动偏移量
                    GeometryReader { innerProxy in
                        Color.clear
                            .preference(key: ScrollOffsetKey.self, value: innerProxy.frame(in: .named("scroll")).minY)
                    }
                )
                .onPreferenceChange(ScrollOffsetKey.self) { value in
                    scrollOffset = value
                }
            }
            .coordinateSpace(name: "scroll")
            .overlay(alignment: .top) {
                VStack(spacing: 0) {
                    // 圆形视图:当滚动偏移量大于圆形高度时,开始跟随滚动滑出
                    Circle()
                        .frame(height: circleHeight)
                        .offset(y: max(scrollOffset - circleHeight, 0))
                        .opacity(scrollOffset > circleHeight ? 0 : 1)
                    
                    // 矩形栏:当滚动偏移量大于圆形高度+栏高度时,固定在顶部;否则跟随滚动
                    HStack {
                        Rectangle()
                            .frame(height: 50)
                            .padding()
                        Rectangle()
                            .frame(height: 50)
                            .padding()
                        Rectangle()
                            .frame(height: 50)
                            .padding()
                    }
                    .background(Color.white) // 背景色覆盖下方内容
                    .offset(y: max(scrollOffset - circleHeight - barHeight, screenTop))
                }
                // 测量圆形和栏的实际高度
                .background(
                    GeometryReader { overlayProxy in
                        Color.clear
                            .onAppear {
                                circleHeight = overlayProxy.frame(in: .local).height / 2
                                barHeight = overlayProxy.frame(in: .local).height / 2
                            }
                    }
                )
            }
        }
    }
}

// 自定义偏好键用于传递滚动偏移量
struct ScrollOffsetKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {}
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

代码说明

  • 滚动偏移监听:通过GeometryReader和自定义PreferenceKey获取ScrollView的滚动偏移量,判断视图是否到达顶部
  • 圆形视图逻辑:初始时跟随滚动,当滚动距离超过自身高度时,逐渐上移并消失,实现"固定后滑出"的效果
  • 矩形栏逻辑:当滚动到其原本位置到达屏幕顶部后,固定在安全区顶部,直到滚动重置
  • 占位视图:在ScrollView内添加透明占位,保证滚动时内容布局不会因为叠加层的固定而出现跳动

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 13:35:18