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

SwiftUI双层粘性头部实现问题求助

实现双层粘性头部(红色头部锚定绿色头部下方)

要让红色的SecondHeaderView始终固定在绿色HeaderView的下方,同时保证SecondView单独使用时自身的粘性头部正常工作,可以通过以下方式调整代码:

修改后的完整代码

struct ContentView: View {
    @State private var headerHeight: CGFloat = 0
    
    var body: some View {
        ScrollView(showsIndicators: false) {
            LazyVStack(spacing: 0, pinnedViews: .sectionHeaders) {
                Section {
                    SecondView(topOffset: headerHeight)
                } header: {
                    HeaderView()
                        .background(
                            GeometryReader { geo in
                                Color.clear
                                    .onAppear {
                                        headerHeight = geo.size.height
                                    }
                            }
                        )
                }
            }
        }
    }
}

struct HeaderView: View {
    var body: some View {
        Rectangle()
            .fill(.green)
            .frame(height: 50)
    }
}

struct SecondView: View {
    let topOffset: CGFloat // 接收外部传递的头部高度,单独使用时传0
    
    var body: some View {
        LazyVStack(spacing: 0, pinnedViews: .sectionHeaders) {
            Section {
                VStack {
                    ForEach(0..<20) { index in
                        ItemView(index: index)
                    }
                }
            } header: {
                SecondHeaderView()
                    .offset(y: topOffset)
                    .padding(.top, -topOffset)
            }
        }
    }
}

struct SecondHeaderView: View {
    var body: some View {
        Rectangle()
            .fill(.red)
            .frame(height: 60)
    }
}

struct ItemView: View {
    let index: Int
    var body: some View {
        VStack {
            Text("Item \(index)")
                .padding()
        }
        .frame(height: 80)
        .background(.gray)
    }
}

#Preview {
    // 测试ContentView
    ContentView()
    
    // 测试单独使用SecondView
    // SecondView(topOffset: 0)
}

关键调整说明

  1. 获取绿色头部高度:在HeaderView的背景中嵌入GeometryReader,获取其高度并保存到headerHeight状态变量中。
  2. 传递偏移量给SecondView:将绿色头部的高度作为topOffset参数传递给SecondView,当SecondView单独使用时,传入0即可保持原有粘性效果。
  3. 调整红色头部的固定位置:给SecondHeaderView添加offset(y: topOffset)让它向下偏移,同时用padding(.top, -topOffset)抵消偏移带来的布局空隙,确保列表内容的位置不受影响。

这样滚动时,红色头部会始终固定在绿色头部的下方,同时SecondView单独使用时,粘性头部会正常固定在屏幕顶部。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 13:39:51