繁体   English   中英

SwiftUI 无法动画化图像过渡

[英]SwiftUI Can't Animate Image Transitions

我正在尝试制作一个简单的图像选择器,我希望从一个图像到另一个图像的过渡是动画的。 似乎是一件非常简单的事情,但我一直找不到单一的解决方案。 我一定在这里遗漏了一些非常简单的东西。

这是一个简化版本:

struct ContentView: View {
    let photos = ["gear", "person", "person.2", "car", "leaf"]

    @State private var currentIndex: Int = 0
    @State private var showAnimation: Bool = true
    private var scalingFactor: CGFloat = 0.5

    var body: some View {

        VStack {
            Text("Image Detection")
                .font(.system(size: 30))
                .fontWeight(.heavy)
                .padding(.top, 30)
        
            Spacer()

            Image(systemName: photos[currentIndex])
                .resizable()
                .frame(width: 250, height: 250)
            //this does nothing
                //.transition(.move(edge: .bottom))
            //this does nothing
                //.animation(.spring(), value: currentIndex)
            //this does nothing
                //.animation(.easeInOut, value: showAnimation)
            //this does nothing
                //.transition(AnyTransition.opacity.animation(.easeInOut(duration: 1.0)))
            //this does nothing
//                .animation(showAnimation ? Animation.easeOut(duration: 2.0) : Animation.easeOut(duration: 1.0), value: showAnimation)

            //this works - but alternates scaled and not with each image
            //and is not really an animation
                .scaleEffect(showAnimation ? 1.0 : 0.5)

            Spacer()
        
            HStack {
                Button(action: {
                    if self.currentIndex >= self.photos.count {
                        self.currentIndex = self.currentIndex - 1
                    } else {
                        self.currentIndex = 0
                    }
                    withAnimation {
                        self.showAnimation.toggle()
                    }
                }, label: {
                    Image(systemName: "arrowtriangle.backward.fill")
                })
                    .padding()
                    .foregroundColor(Color.blue)
                    .font(.largeTitle)

                Spacer()
            
                Button(action: {
                    if self.currentIndex < self.photos.count - 1 {
                        self.currentIndex = self.currentIndex + 1
                    } else {
                        self.currentIndex = self.photos.count - 1
                    }
                    withAnimation {
                        self.showAnimation.toggle()
                    }
                }, label: {
                    Image(systemName: "arrowtriangle.forward.fill")
                })
                    .padding()
                    .foregroundColor(Color.blue)
                    .font(.largeTitle)

            }
            .padding(.horizontal, 50)

            Spacer()
        }//v
    }//body
}//content view

任何指导将不胜感激。 Xcode 13.2.1 iOS 15.2

SwiftUI 的当前方法是使用 .transition .transition() ,因为.animation()已被弃用。

重要的是要理解.transition()在视图出现或消失时被触发。 您的视图不会因为您更改@State变量而完全重新绘制:在您的代码中, Image发生更改但它始终保留在视图中。

一种解决方案是触发图像完全消失并重新出现新图像。 下面的代码执行此操作,具体取决于 showAnimation 的showAnimation 看到我只使用了.transition() ,但效果很好:

  • 它是不对称的
  • withAnimation()闭包也包装了currentIndex的变化
struct Example: View {
    let photos = ["gear", "person", "person.2", "car", "leaf"]

    @State private var currentIndex: Int = 0
    @State private var showAnimation: Bool = true
    private var scalingFactor: CGFloat = 0.5

    var body: some View {

        VStack {
            Text("Image Detection")
                .font(.system(size: 30))
                .fontWeight(.heavy)
                .padding(.top, 30)
        
            Spacer()
            
            if showAnimation {
                image
            } else {
                image
            }

            Spacer()
        
            HStack {
                Button(action: {
                    withAnimation {
                        showAnimation.toggle()
                        if self.currentIndex >= self.photos.count {
                            self.currentIndex = self.currentIndex - 1
                        } else {
                            self.currentIndex = 0
                        }
                    }
                }, label: {
                    Image(systemName: "arrowtriangle.backward.fill")
                })
                    .padding()
                    .foregroundColor(Color.blue)
                    .font(.largeTitle)

                Spacer()
            
                Button(action: {
                    withAnimation {
                        showAnimation.toggle()
                        if self.currentIndex < self.photos.count - 1 {
                            self.currentIndex = self.currentIndex + 1
                        } else {
                            self.currentIndex = self.photos.count - 1
                        }
                    }
                }, label: {
                    Image(systemName: "arrowtriangle.forward.fill")
                })
                    .padding()
                    .foregroundColor(Color.blue)
                    .font(.largeTitle)

            }
            .padding(.horizontal, 50)

            Spacer()
        }//v
    }//body
    
    private var image: some View {
        Image(systemName: photos[currentIndex])
            .resizable()
            .frame(width: 250, height: 250)
            .transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)))
    }
}

暂无
暂无

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

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