I have the following custom action sheet with options (details omitted for simplicity):
var sheet: some View {
VStack {
HStack { /* some stuff here */ }
list(of: options)
.readSize($optionsSize)
.wrappedInScrollView(when: optionsDontFit)
.transition(.opacity)
}
.readSize($sheetSize)
}
where:
list(of:)is just aVStackarranging all options' viewsreadSize(…)is a modifier I created that updates a provided binding via aGeometryReader;optionsDontFitis a computed Bool property (depending onsheetSizeandoptionsSize);wrappedInScrollView(when:)is the following:
fileprivate extension View {
@ViewBuilder
func wrappedInScrollView(when condition: Bool) -> some View {
if condition {
ScrollView {
self
}
} else {
self
}
}
}
The problem arises when the parent of the sheet is animated e.g. via a transition from the bottom:
var body: some View {
ZStack {
/* some stuff here */
VStack {
Spacer(minHeight: 42)
if !isDismissed {
sheet.transition(.move(edge: .bottom))
}
}
}
.onAppear { isDismissed = false }
}
The issue is that the sheet itself does not slide with the parent, but appears instead directly at the final position. The closing (dismissing) animation however works as expected.
If I remove the scrollview wrapper func, eveything is fine.
Here is a screen rec of the problem:
Any idea what is going on?
I tried removing the scrollview wrapper func, and it animates correctly, but I have a requirement that the options list should be scrollable on smaller devices where the options take up the entire screen.
I tried moving the transition modifiers elsewhere but to no avail (also those should be the correct places).
I tried putting a transition(edge: .bottom) for the list(of:) as well but this will not work in some other scenarios with the full code I have (I actually have a switch-case over there that either presents a loader, or a list, so when state is changed while it is loading it reappears from the bottom of the screen while the parent is already moving further above).

ScrollViewis causing the issue then you could maybe try the technique shown as answer to How to keep the ScrollView height to the minimum necessary in SwiftUI?, as replacement for yourwrappedInScrollViewapproach.readSizemodifier uses aColor.clear.onAppearapproach, a slight fraction of the second after things are on screen the value ofoptionsDontFitchanges and produces a new tree without a scroll view, which has this problematic animation.