Ich habe die folgende Version erreicht, vertraue ihr aber nicht allzu sehr und sie ist auch nicht sehr flüssig.
Code: Select all
// MARK: - B over A with dynamic offset; A interactive while visible
struct CollapsingOverlayScrollExample: View {
private let headerHeight: CGFloat = 200
@State private var scrolledUp: CGFloat = 0
@State private var baselineTop: CGFloat? = nil
@State private var displayedScrolledUp: CGFloat = 0
var body: some View {
ZStack(alignment: .top) {
// View A (Header) behind
VStack {
Text("👆 Tap Header (A)")
.font(.headline)
.foregroundColor(.white)
Text("Visible part remains interactive")
.foregroundColor(.white)
}
.frame(height: headerHeight)
.frame(maxWidth: .infinity)
.background(Color.blue)
.onTapGesture {
print("👉 Header (A) tapped!")
}
.zIndex(0)
// View B (ScrollView) on top, offset down by remaining visible header
ScrollView {
VStack(spacing: 20) {
// Sentinel to track scroll offset within the ScrollView
GeometryReader { geo in
Color.clear
.preference(key: ScrollOffsetKey.self,
value: geo.frame(in: .named("ROOT")).minY)
}
.frame(height: 0)
ForEach(1...30, id: \.self) { i in
Text("Scroll Item \(i)")
.frame(maxWidth: .infinity)
.frame(height: 60)
.background(Color.orange.opacity(0.9))
.cornerRadius(8)
.padding(.horizontal)
}
}
.padding(.top, 16)
}
.background(Color.green.opacity(0.5))
// While header is visible, keep B's frame below it so A remains tappable
.offset(y: max(0, headerHeight - displayedScrolledUp))
.zIndex(1)
}
.coordinateSpace(name: "ROOT")
.onPreferenceChange(ScrollOffsetKey.self) { topInRoot in
// Calibrate baseline once to avoid initial jump due to layout timing.
if baselineTop == nil {
baselineTop = topInRoot
}
let base = baselineTop ?? headerHeight
// Positive distance scrolled upwards relative to the baseline.
let delta = base - topInRoot
scrolledUp = max(0, delta)
}
.onChange(of: scrolledUp) { newValue in
withAnimation(.interactiveSpring(response: 0.25, dampingFraction: 0.86, blendDuration: 0.2)) {
displayedScrolledUp = newValue
}
}
.edgesIgnoringSafeArea(.all)
}
}
Mobile version