SwiftUI中ScrollView中的动画过渡和内容

SwiftUI中ScrollView中的动画过渡和内容,swiftui,transition,swiftui-animation,Swiftui,Transition,Swiftui Animation,我并不是一个SwiftUI的老手,但我已经发布了一些中等复杂度的应用程序。尽管如此,我不能说我完全理解这一点,我希望有更深入的知识的人能够对这一问题有所了解: 我有一些内容要打开和关闭,这与.sheet()不同,但我希望对其进行更多的控制。下面是一些“重建”的代码,但它应该能够抓住本质: struct ContentView:View{ @国家私有变量isShown=false var body:一些观点{ GeometryReader{g in VStack{ ZStack(对齐:。顶部){

我并不是一个SwiftUI的老手,但我已经发布了一些中等复杂度的应用程序。尽管如此,我不能说我完全理解这一点,我希望有更深入的知识的人能够对这一问题有所了解:

我有一些内容要打开和关闭,这与.sheet()不同,但我希望对其进行更多的控制。下面是一些“重建”的代码,但它应该能够抓住本质:

struct ContentView:View{
@国家私有变量isShown=false
var body:一些观点{
GeometryReader{g in
VStack{
ZStack(对齐:。顶部){
//此元素“保存”大小
//而内容是隐藏的
颜色。清晰
//要切换的内容
如果self.isShown{
滚动视图{
矩形()
.aspectRatio(1,contentMode:.fit)
.frame(宽度:g.size.width)//这是一个“变通方法”
}//滚动视图
.transition(.move(边:。底部))
.animation(.easeOut)
}
}//ZStack
//按钮以显示/隐藏内容
按钮(操作:{
self.isShown.toggle()
}) {
文本(self.isShown?“隐藏”:“显示”)
}
}//VStack
}//GeometryReader
}
}
它所做的是,它打开和关闭一些内容块(这里由ScrollView中的一个矩形表示)。当这种情况发生时,中的内容视图通过从底部移入一些动画进行转换。当再次点击按钮时,情况正好相反

这段特定的代码按预期工作,但仅因为这一行:

.frame(宽度:g.size.width)//这是一个“变通方法”
这反过来又需要一个额外的GeometryReader,否则,内容的宽度会被动画化,产生不想要的效果(我发现的另一个“修复”是使用.fixedSize()修饰符,但为了产生合理的效果,它需要像文本一样具有自身宽度的内容)

我向智者提出的问题是:是否有可能在不使用此类“修复”的情况下,在ScrollView中封装的内容中进行良好的转换?或者,是否有更优雅的解决方案

在@Asperi的回答之后,快速添加一个问题:内容应该保持动画效果。 你是我唯一的希望

–Baglan

这里有一个解决方案(更新的
正文
w/o
GeometryReader
)。使用Xcode 11.4/iOS 13.4进行测试

var主体:一些视图{
VStack{
ZStack(对齐:。顶部){
//此元素“保存”大小
//而内容是隐藏的
颜色。清晰
//要切换的内容
如果self.isShown{
滚动视图{
矩形()
.aspectRatio(1,contentMode:.fit)

.动画(无)//您好,谢谢您的回答,这是一个有效的解决方案!我能看到的唯一问题是,我可能希望为内容设置动画。在实际项目中,有一些子视图以类似的方式显示动画或过渡,并且将动画设置为“零”会阻止这些。当然,您无法从代码中推断出这一点:)。不过,这是一个有效的答案,谢谢!我也有一个类似的问题,就是想在子视图中添加动画
var body: some View {
    VStack {
        ZStack(alignment: .top) {
            // This element "holds" the size
            // while the content is hidden
            Color.clear

            // Content to be toggled
            if self.isShown {
                ScrollView {
                    Rectangle()
                        .aspectRatio(1, contentMode: .fit)
                        .animation(nil)     // << here !!
                } // ScrollView
                    .transition(.move(edge: .bottom))
                    .animation(.easeOut)
            }
        } // ZStack

        // Button to show / hide the content
        Button(action: {
            self.isShown.toggle()
        }) {
            Text(self.isShown ? "Hide" : "Show")
        }
    } // VStack
}