ios - SwiftUI-如何取消默认列表动画

标签 ios swift swiftui

有没有一种方法可以删除默认的列表行折叠动画
在列表本身上不使用.animation(nill)修饰符?

正如您在下面的剪辑中看到的那样,我已经在列表上实现了动画修饰符,但是默认的列表折叠动画有点干扰了所需的动画。

https://gfycat.com/cheerywelloffalleycat

我已经更新了以下代码,因此您可以在Xcode上运行它而无需任何依赖。

  import SwiftUI

struct CurrencyComparison: View {
    @State var mainArray = ["10", "10","10", "10", "10", "10", "10", "10", "10", "10"]
    @State var array = ["10", "10","10", "10", "10", "10", "10", "10", "10", "10"]
    @State var secondArray = ["20", "20","20", "20", "20", "20", "20", "20", "20", "20"]
    @State var hide = false
    @State var direction = false
    @State var triggerAnimation: Bool


    var body: some View {
        VStack {


                List (self.mainArray, id:\.self) { item in

                    Text(item)
                        .foregroundColor(Color.black)
                        .frame(width: 40, height: 80)
                        .padding(.leading, 80)
                        .isHidden(self.hide)
                    Spacer()
                    Text(item)
                        .foregroundColor(Color.black)
                        .frame(width: 40, height: 40)
                        .padding(.trailing, 80)
                        .isHidden(self.hide)
                }
                .background(LinearGradient(gradient: Gradient(colors: [Color.blue, Color.red]), startPoint: .center, endPoint: .center))
                .animation(Animation.spring().delay(triggerAnimation ? 0 : 0.4))
                .transition(.asymmetric(insertion: AnyTransition.opacity.combined(with: .move(edge: .trailing)), removal: .move(edge: .trailing)))
                .cornerRadius(30)
                .padding(.top, 30)
                .padding(.bottom, 30)
                .shadow(radius: 10)
                .gesture(
                    DragGesture(minimumDistance: 50)

                        .onEnded { value in
                            self.hide.toggle()

                            DispatchQueue.main.asyncAfter(deadline: .now() ) {
                                if self.mainArray == self.array {
                                    self.mainArray = self.secondArray
                                } else {
                                    self.mainArray = self.array
                                }
                            }
                            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                                self.hide.toggle()
                            }
                    }
                )
        }
        .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height + 50, alignment: .top)
        .background(Color.gray.aspectRatio(contentMode: .fill))
        .padding(.top, 120)
    }
}

struct CurrencyComparison_Previews: PreviewProvider {
    @State static var staticBool = true
    static var previews: some View {
        CurrencyComparison(triggerAnimation: true)
    }
}


extension View {
    func isHidden(_ bool: Bool) -> some View {
        modifier(HiddenModifier(isHidden: bool))
    }
}

private struct HiddenModifier: ViewModifier {

    fileprivate let isHidden: Bool

    fileprivate func body(content: Content) -> some View {
        Group {
            if isHidden {
                content.hidden()

            } else {
                content
                    .transition(.asymmetric(insertion: AnyTransition.opacity.combined(with: .slide), removal: .move(edge: .trailing)))

            }
        }
    }
}

最佳答案

好的,我设法找到了可行的解决方案。通过在列表数据源发生更改时更改列表项的不透明度。

不需要的默认动画播放时将其设置为0,并在所需的动画开始播放时将其恢复为1。

这样,我可以隐藏默认列表动画,而无需删除自己想要的动画:)

import SwiftUI

struct CurrencyComparison: View {
    @State var mainArray = ["10", "10","10", "10", "10", "10", "10", "10", "10", "10"]
    @State var array = ["10", "10","10", "10", "10", "10", "10", "10", "10", "10"]
    @State var secondArray = ["20", "20","20", "20", "20", "20", "20", "20", "20", "20"]
    @State var toggleHide = false
    @State var direction = false
    @State var triggerAnimation: Bool


    var body: some View {
        VStack {
            List (self.mainArray, id:\.self) { item in

                Text(item)
                    .foregroundColor(Color.black)
                    .frame(width: 40, height: 80)
                    .padding(.leading, 80)
                    .isHidden(self.toggleHide)
                    .opacity(self.toggleHide ? 0 : 1)
                Spacer()
                Text(item)
                    .foregroundColor(Color.black)
                    .frame(width: 40, height: 40)
                    .padding(.trailing, 80)
                    .isHidden(self.toggleHide)
                    .opacity(self.toggleHide ? 0 : 1)
            }
            .background(LinearGradient(gradient: Gradient(colors: [Color.blue, Color.red]), startPoint: .center, endPoint: .center))
            .animation(Animation.spring().delay(triggerAnimation ? 0 : 0.4))
            .transition(.asymmetric(insertion: AnyTransition.opacity.combined(with: .move(edge: .trailing)), removal: .move(edge: .trailing)))
            .cornerRadius(30)
            .padding(.top, 30)
            .padding(.bottom, 30)
            .shadow(radius: 10)
            .gesture(
                DragGesture(minimumDistance: 50)

                    .onEnded { value in
                        self.toggleHide.toggle()

                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                            if self.mainArray == self.array {
                                self.mainArray = self.secondArray
                            } else {
                                self.mainArray = self.array
                            }
                        }

                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.9) {
                            self.toggleHide.toggle()
                        }
                }
            )
        }
        .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height + 50, alignment: .top)
        .background(Color.gray.aspectRatio(contentMode: .fill))
        .padding(.top, 120)
    }
}

struct CurrencyComparison_Previews: PreviewProvider {
    @State static var staticBool = true
    static var previews: some View {
        CurrencyComparison(triggerAnimation: true)
    }
}


extension View {
    func isHidden(_ bool: Bool) -> some View {
        modifier(HiddenModifier(isHidden: bool))
    }
}

private struct HiddenModifier: ViewModifier {

    fileprivate let isHidden: Bool

    fileprivate func body(content: Content) -> some View {
        Group {
            if isHidden {
                content.hidden()

            } else {
                content
                    .transition(.asymmetric(insertion: AnyTransition.opacity.combined(with: .slide), removal: .move(edge: .trailing)))

            }
        }
    }
}

关于ios - SwiftUI-如何取消默认列表动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59966859/

相关文章:

ios - 如何制作像 Instagram 一样的导航栏

ios - 有什么方法可以快速绘制和分析数据吗?

json - 如何在 SwiftUI 中解码来自 API 的 JSON 响应以在 View 中使用

swift - @ObjectBinding 不适用于协议(protocol)

swift - 将 SwiftUI 颜色转换为 UIColor

objective-c - 如何使用ffmpeg解压缩压缩类型的音频文件?

ios - 表情符号键盘布局未正确绘制并且缺少许多表情符号

android - Flutter 将 Uint8List 传递给 iOS Objective-c

ios - UIStackView 里面的 UIScrollView 位置

ios - didSelectItemAt 无法从 SCLAlertView 工作