I'm trying to build a profile-style screen similar to X (Twitter), Instagram, or YouTube.
The layout is roughly:
┌──────────────────────────┐
│ Profile Header │
│ Cover image │
│ Avatar │
│ Bio / Stats │
└──────────────────────────┘
┌──────────────────────────┐
│ Tab Bar │
│ Posts | Media | Likes │
└──────────────────────────┘
┌──────────────────────────┐
│ Tab Content │
│ │
│ ScrollView / List │
│ OR │
│ Empty State VStack │
│ │
└──────────────────────────┘
Requirements:
-
The profile header should collapse while scrolling up.
-
The tab bar should remain pinned.
-
Once the header is fully collapsed, the active tab's scroll view should start scrolling.
-
While scrolling down, the active tab should scroll back to the top first, then the header should expand.
-
Some tabs may contain:
ScrollView + LazyVStackList- a non-scrollable
VStack(for empty states)
-
The behavior should remain consistent regardless of which tab is active.
This feels very similar to Jetpack Compose's NestedScrollConnection, where parent and child scroll containers can cooperatively consume scroll deltas.
In SwiftUI, I have explored:
ScrollViewGeometryReaderPreferenceKey- Scroll offset tracking
- Custom
UIScrollViewwrappers - A
UIViewControllerRepresentableapproach that intercepts pan gestures and coordinates scrolling manually
However, I haven't found a SwiftUI-native way for a parent container and child scroll view to negotiate scroll consumption.
My questions are:
- Does SwiftUI provide any equivalent to Compose's
NestedScrollConnection? - Is there a recommended way to implement this profile-screen pattern purely in SwiftUI?
- How are people handling cases where some tabs contain scrollable content while other tabs contain only static content?
- Is bridging to UIKit currently the only practical solution for this kind of coordinated scrolling behavior?
Any guidance or examples would be greatly appreciated.