如何解决在过渡中奇怪和不需要的SwiftUI动画?

huangapple go评论87阅读模式
英文:

How to solve weird and unwanted SwiftUI Animation in transition?

问题

在这段代码中,我使用SwiftUI View来创建macOS Cocoa中的内容。我对动画的问题感到困惑,即在添加或移除圆圈时,内容会出现意外的跳动。我需要保留的过渡效果,但不希望内容在添加或移除圆圈时上下跳动。如何解决这个跳动问题?

import Cocoa
import SwiftUI

class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.wantsLayer = true
        self.view = NSHostingView(rootView: ContentView())
    }

}

struct ContentView: View {
    
    @State private var myArray: [CustomType] = [CustomType(1), CustomType(2), CustomType(3), CustomType(4), CustomType(5)]
    
    var body: some View {
        
        VStack(spacing: 20) {
            
            ForEach(myArray, id:\.id) { item in
                
                Circle()
                    .fill(Color.red)
                    .frame(width: 100.0, height: 100.0)
                    .overlay(content: {
                        Text(String(describing: item.value))
                            .font(Font.system(.largeTitle, design: .monospaced))
                    })
                    .transition(AnyTransition.scale)
                
            }
            
            Button("add") {
                myArray.append(CustomType(myArray.count + 1))
            }
            
            Button("remove") {
                if (myArray.count > 0) { myArray.removeLast() }
            }
        }
        .padding(30)
        .animation(.linear(duration: 0.2), value: myArray.count)
        
    }
    
    struct CustomType: Identifiable {
        
        let id: UUID = UUID()
        var value: Int
        
        init(_ value: Int) {
            self.value = value
        }
        
    }
    
}
英文:

I am using a SwiftUI View for my content in macOS Cocoa in this code:

import Cocoa
import SwiftUI

class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.wantsLayer = true
        self.view = NSHostingView(rootView: ContentView())
    }

}

struct ContentView: View {
    
    @State private var myArray: [CustomType] = [CustomType(1), CustomType(2), CustomType(3), CustomType(4), CustomType(5)]
    
    var body: some View {
        
        VStack(spacing: 20) {
            
            ForEach(myArray, id:\.id) { item in
                
                Circle()
                    .fill(Color.red)
                    .frame(width: 100.0, height: 100.0)
                    .overlay(content: {
                        Text(String(describing: item.value))
                            .font(Font.system(.largeTitle, design: .monospaced))
                    })
                    .transition(AnyTransition.scale)
                
            }
            
            Button("add") {
                myArray.append(CustomType(myArray.count + 1))
            }
            
            Button("remove") {
                if (myArray.count > 0) { myArray.removeLast() }
            }
        }
        .padding(30)
        .animation(.linear(duration: 0.2), value: myArray.count)
        
    }
    
    struct CustomType: Identifiable {
        
        let id: UUID = UUID()
        var value: Int
        
        init(_ value: Int) {
            self.value = value
        }
        
    }
    
}

The issue that I have with the animation is an unwanted jump! The content jumps up or down in addition or removal of Circles. The transition that I am using is needed as the effect but that jump to up or down is not what I want. How to solve this jump issue?

答案1

得分: 1

如果您希望事物不是立即定位,而是以动画方式变化,您需要将状态更改封装在withAnimation块中。

看起来会像这样:


            Button("添加") {
                withAnimation {
                    myArray.append(CustomType(myArray.count + 1))
                }
            }
            
            Button("移除") {
                if (myArray.count > 0) { 
                    withAnimation {
                        myArray.removeLast() 
                    }
                }
            }

如何解决在过渡中奇怪和不需要的SwiftUI动画?

英文:

If you want things to animate instead of snap into place, you need to wrap the state changes in a withAnimation block.

It would look like this:

 
            Button("add") {
                withAnimation {
                    myArray.append(CustomType(myArray.count + 1))
                }
            }
            
            Button("remove") {
                if (myArray.count > 0) { 
                    withAnimation {
                        myArray.removeLast() 
                    }
                }
            }

如何解决在过渡中奇怪和不需要的SwiftUI动画?

huangapple
  • 本文由 发表于 2023年3月12日 10:20:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/75710733.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定