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

如何根据滚动位置切换ScrollTargetBehavior的行为模式?

问题:实现混合滚动行为(顶部分页+下方自由滚动)

我正在开发一款应用,在「探索」内容前展示一个或多个全屏特色视图(类似Spotify首页)。当前代码结构如下:

GeometryReader { proxy in
        let h = proxy.size.height
        
        ScrollView {
          if data == nil {
            Recommended(event: nil)
              .padding(.vertical, 8)
              .frame(height: h)
              .frame(maxWidth: .infinity)
          } else {
            LazyVStack(spacing: proxy.safeAreaInsets.bottom / 2) {
              ForEach(data?.recommended ?? []) { _ in
                Recommended(event: events[0])
                  .padding(.vertical, 8)
                  .frame(height: h)
                  .frame(maxWidth: .infinity)
                  .padding(.bottom, proxy.safeAreaInsets.bottom / 2)
              }
            }
            .scrollTargetLayout()
          }
          
          if let sections = data?.sections {
            LazyVStack(spacing: 32) {
              ForEach(Array(sections.enumerated()), id: \.offset) { e in
                let section = e.element
                  
                EventRow(title: section.title, events: section.events)
              }
            }
            .scrollTargetLayout()
          }
          
          Spacer()
        }
    //    .scrollPosition(id: $scrollID) this was an attempt
    //    .scrollTargetBehavior(.custom) this was another attempt
        .scrollDisabled(data == nil)
        .scrollIndicators(.hidden)
        .ignoresSafeArea(.container)
        .refreshable {
          print("refresh")
        }
        .onChange(of: scrollID) { _, newValue in
          print(newValue ?? "")
        }
      }

尝试基于scrollID切换分页样式时,使用三元表达式出现以下错误:

.scrollTargetBehavior(true ? .paging : .viewAligned)

Member 'viewAligned' in 'PagingScrollTargetBehavior' produces result of type 'ViewAlignedScrollTargetBehavior', but context expects 'PagingScrollTargetBehavior'

我也尝试过自定义实现scroll target behavior,但未取得理想效果。

以下是最小可复现示例:

struct ContentView: View {
  let colors: [Color] = [.blue, .green, .yellow, .red]

  var body: some View {
    GeometryReader { proxy in
      ScrollView(.vertical) {
        LazyVStack(spacing: proxy.safeAreaInsets.bottom / 2) {
          ForEach(0 ..< 2) { i in
            ZStack {
              Rectangle()
                .fill(colors[i % colors.count].opacity(0.6))
                .containerRelativeFrame([.horizontal, .vertical])
                .padding(.bottom, proxy.safeAreaInsets.bottom / 2)
                .frame(
                  width: proxy.size.width,
                  height: proxy.size.height + (proxy.safeAreaInsets.bottom / 2)
                )
              Text("Video \(i + 1)")
                .font(.title)
                .bold()
            }
          }
        }
        .scrollTargetLayout()
        
        // these elements should scroll normally without snapping
        ForEach(0 ..< 20) { i in
          Rectangle()
            .fill(.purple)
            .frame(width: 100, height: 100)
            .overlay {
              Text("\(i)")
            }
        }
      }
      .scrollTargetBehavior(.paging)
      .ignoresSafeArea(edges: .bottom)
    }
  }
}

#Preview {
  ContentView()
}

核心需求

顶部全屏视图使用分页滚动,下方普通视图正常滚动,需根据滚动位置切换ScrollTargetBehavior。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:03:16