简体   繁体   English

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

[英]SwiftUI - how to cancel the default list animation

Is there a way to remove the default list row collapse animation without using .animation(nill) modifier on the list itself?有没有办法在不使用列表本身的 .animation(nill) 修饰符的情况下删除默认列表行折叠动画?

as you can see in the clip below, I've implemented an animation modifier on the list, but the default list collapse animation kinda disrupts the desired animation.正如您在下面的剪辑中看到的那样,我在列表中实现了一个动画修改器,但是默认的列表折叠动画有点破坏了所需的动画。

https://gfycat.com/cheerywelloffalleycat https://gfycat.com/cheerywelloffalleycat

I've updated the code below so you could run it on your Xcode without any dependencies.我已经更新了下面的代码,这样你就可以在你的 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)))

            }
        }
    }
}

Okay so I've managed to find a solution that works.好的,所以我设法找到了一个有效的解决方案。 By changing the opacity of the list items when the list data source change happens.通过在列表数据源发生更改时更改列表项的不透明度。

Setting it to 0 when the undesired default animation play, and bringing it back to 1 when my the desired animations start playing.当不需要的默认动画播放时将其设置为 0,并在我想要的动画开始播放时将其恢复为 1。

That way I can hide the default list animation without removing my own desired animations :)这样我就可以隐藏默认列表动画而不删除我自己想要的动画:)

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)))

            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM