如何根据滚动位置切换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
相关产品推荐
相关产品推荐

