With the extensive help of Benzy Neez I managed to find my very own solution. If thee is a pitfall, please let me know ...
struct WingList: View {
let wings: [Wing]
@State private var scrollPos = CGFloat.zero
var body: some View {
GeometryReader { proxy in
let fullHeight = proxy.size.width / 1280 * 800
ScrollView {
LazyVStack(spacing: 3, content: {
ForEach(Array(wings.enumerated()), id: \.element.id) { index, wing in
WingListItem(wing: wing, height: calcFrameHeight(index: index, fullHeight: fullHeight))
}
Spacer(minLength: 550) // This is just a brute method, I know
})
}
.onScrollGeometryChange(
for: CGFloat.self,
of: { scrollGeometry in
scrollGeometry.contentOffset.y
},
action: { oldValue, newValue in
scrollPos = newValue
}
)
}
}
func calcFrameHeight(index: Int, fullHeight: CGFloat) -> CGFloat {
let offset = CGFloat(index) * (fullHeight + 3) - scrollPos - 100 // 100 added because the safeAreaInset in the parent view
if offset < 0 {
return fullHeight
} else if offset < fullHeight {
return (fullHeight - 100) * (1 - offset / fullHeight) + 100
} else {
return 100
}
}
}
struct WingListItem: View {
let wing: Wing
let height: CGFloat
var body: some View {
Image(uiImage: wingImage())
.resizable()
.aspectRatio(contentMode: .fill)
.frame(height: height, alignment: .top)
}
}