ios - ScrollView 中的 SwiftUI 动画/过渡表现奇怪

标签 ios swift animation swiftui scrollview

我在 SwiftUI 中有一个带有多个元素的 ScrollView,其中一些元素在点击时会展开。

struct ExpandingView: View {

    @State var showContent = false

    var body: some View {
        VStack {
            HStack {
                Button(action: {withAnimation {
                        self.showContent.toggle()
                    }
                }) {
                    Image(systemName: "chevron.right.circle")
                }
                Text("TITLE")
                    .padding(.leading, 10)
                Spacer()
            }
            if showContent {
                Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras volutpat dapibus ante eget laoreet. Aenean lacus elit, auctor ut nisl id, fermentum pretium mi. Quisque lacus nisl, suscipit hendrerit est sed, congue dictum augue. Suspendisse semper viverra accumsan. Maecenas commodo turpis convallis nisl bibendum pharetra.")
                    .transition(AnyTransition.move(edge: .top).combined(with: .opacity))
            }
        }
    }
}

struct Test: View {

    var body: some View {
        ScrollView {
            ExpandingView()
            ExpandingView()
            ExpandingView()
            Text("Some static text")
        }
    }
}

如果您尝试打开其中一个展开的文本,您会看到过渡并不顺畅,有点像跳跃,然后过渡开始。

https://media.giphy.com/media/cjhClEVwgsEQpkBGAv/giphy.gif

所以这是我尝试过的:
  • 如果我删除 ScrollView 并将其放到 VStack 中,例如它工作正常,但这不是一个选项,因为我有更多的元素不适合屏幕。
  • 我尝试为 ScrollView 设置动画,因为我读到它解决了此类问题,如下所示:
  • ScrollView {
                ExpandingView()
                ExpandingView()
                ExpandingView()
                Text("Some static text")
            }.animation(.spring())
    

    它在打开过渡方面工作得很好,它甚至看起来更好用 Spring 效果,但整个 ScrollView 的 Spring 动画在 View 出现时播放,这是我不想要的。

    https://media.giphy.com/media/lTMG9mGD0X0qrksYtB/giphy.gif

    同样,如果我将 ScrollView 更改为 VStack,动画不会在出现时播放,这很好,但我必须使用 ScrollView 。所以对我来说最好的解决方案是保留打开文本的动画,但在 View 出现时以某种方式将其删除。

    最佳答案

    这是可能的解决方案。另请阅读内联评论。使用 Xcode 11.4/ISO 13.4 测试

    demo

    struct ExpandingView: View {
    
        @State var showContent = false
    
        var body: some View {
            VStack {
                HStack {
                    Button(action: {
                            self.showContent.toggle()
                    }) {
                        Image(systemName: "chevron.right.circle")
                    }
                    Text("TITLE")
                        .padding(.leading, 10)
                    Spacer()
                }
                if showContent {
                    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras volutpat dapibus ante eget laoreet. Aenean lacus elit, auctor ut nisl id, fermentum pretium mi. Quisque lacus nisl, suscipit hendrerit est sed, congue dictum augue. Suspendisse semper viverra accumsan. Maecenas commodo turpis convallis nisl bibendum pharetra.")
                        .fixedSize(horizontal: false, vertical: true)
                        .transition(AnyTransition.move(edge: .top).combined(with: .opacity))
                }
            }
        }
    }
    
    struct DemoExpandingView: View {
    
        // initial nil to avoid initial animation
        @State private var animation: Animation? = nil
        var body: some View {
            ScrollView {
                VStack {
                    ExpandingView()
                    ExpandingView()
                    ExpandingView()
                    Text("Some static text")
                }.animation(animation) // << needed to animate static section
            }
            .onAppear {
                DispatchQueue.main.async {
                    // assign in-container animation `after` container rendered
                    self.animation = .default
                }
            }
        }
    }
    

    关于ios - ScrollView 中的 SwiftUI 动画/过渡表现奇怪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61698182/

    相关文章:

    iphone - ipad 和 iphone safari 上 div 的单个/子像素未对齐

    ios - 我对如何在实例被取消初始化时操作实例内部的属性感到困惑?

    ios - 我应该在 iOS 应用程序中的什么位置存储默认字符串列表?

    swift - 如何快速将地址从应用程序传递到谷歌地图,而不仅仅是纬度和经度

    Swift 4 使用泛型作为返回值

    jquery粒子生成器

    ios - 如何在 iOS 中同时为平移和高度设置动画

    ios - 如何检测 ios8 自定义键盘扩展是否在非 iphone 6 优化的应用程序中运行?

    ios - 长按手势识别器生成重复位置 (SWIFT)

    ios - 来自 UITableView 的 deleteRowsAtIndexPaths :withRowAnimation: 的不规则动画