【发布时间】:2021-05-23 03:42:48
【问题描述】:
我正在尝试创建一个应用程序,其中有多个视图可以在它们之间转换,其中包含动画。到目前为止,这是通过在 scrollView 中为 VStack 的偏移量设置动画来完成的,其中偏移量是通过将屏幕高度乘以当前屏幕的索引来计算的。我决定采用这条路线而不是使用 scrollTo,因为我想自定义过渡动画以缓入和缓出。
这是 ContentView 代码:
import SwiftUI
struct ContentView: View {
@Namespace var carousel
@Namespace var splash
@Namespace var home
@State private var activeIndex = CGFloat(0)
var body: some View {
GeometryReader { geo in
ScrollViewReader { proxy in
ScrollView([]) {
VStack (spacing: 0) {
ZStack {
Color.red
Splash(home: home, geo: geo, proxy: proxy)
.frame(width: geo.size.width, height: geo.size.height, alignment: .leading)
.id(splash)
}
ZStack {
Color.blue
VStack {
Home(activeIndex: self.$activeIndex, splash: splash, home: home, geo: geo, proxy: proxy)
.frame(width: geo.size.width, height: geo.size.height, alignment: .leading)
.offset(y: -200)
.id(home)
}
}
}
.offset(y: activeIndex > 0 ? -geo.size.height * activeIndex + 200 : -geo.size.height * activeIndex)
.animation(.easeInOut(duration: 0.8))
.id(carousel)
}
.frame(width: geo.size.width, height: geo.size.height)
}
}.ignoresSafeArea()
}
}
这是按钮所在的代码:
import SwiftUI
struct Home: View {
@Binding var activeIndex: CGFloat
var splash: Namespace.ID
var home: Namespace.ID
var geo: GeometryProxy
var proxy: ScrollViewProxy
var body: some View {
VStack (alignment: .leading, spacing: 0) {
HStack {
Spacer()
VStack {
Button(activeIndex == 0 ? "Let's go" : "Go Back") {
if activeIndex == 0 {
self.activeIndex = 1;
}
else {
self.activeIndex = 0;
}
}
.frame(width: 200, height: 50)
.font(.custom("Montserrat-SemiBold", size: 18))
.background(Color.green)
.cornerRadius(25)
.foregroundColor(.white)
.offset(y: 25)
}
Spacer()
}
.zIndex(1)
VStack {
}
.frame(width: geo.size.width, height: geo.size.height * 0.8, alignment: .leading)
.background(Color.white)
.cornerRadius(40)
}
.frame(width: geo.size.width, height: geo.size.height, alignment: .leading)
.cornerRadius(40)
}
}
Here's a gif of the functionality so far
我想为主页上的“Let's Go”按钮设置动画,使其轻微摆动,然后当按下它时,动画在屏幕转换开始时停止。但是,这并不像我想象的那么容易,因为这个动画似乎受到了 ContentView 中 VStack 上的动画的影响。
这是我制作此动画的尝试:
import SwiftUI
struct Home: View {
@State private var isAnimating = false
@State private var stopAnimating = false
@Binding var activeIndex: CGFloat
var splash: Namespace.ID
var home: Namespace.ID
var geo: GeometryProxy
var proxy: ScrollViewProxy
var body: some View {
VStack (alignment: .leading, spacing: 0) {
HStack {
Spacer()
VStack {
Button(activeIndex == 0 ? "Let's go" : "Go Back") {
if activeIndex == 0 {
self.activeIndex = 1;
}
else {
self.activeIndex = 0;
}
isAnimating.toggle()
stopAnimating.toggle()
}
.frame(width: 200, height: 50)
.font(.custom("Montserrat-SemiBold", size: 18))
.background(Color.green)
.cornerRadius(25)
.foregroundColor(.white)
.offset(y: 25)
.shadow(color: Color.black.opacity(0.35), radius: 10)
.rotationEffect(Angle(degrees: self.isAnimating ? 5 : self.stopAnimating ? 0 : -5))
.animation(self.isAnimating ? Animation // Animation added
.easeInOut(duration: 0.2)
.repeatForever() : .default, value: self.isAnimating)
.onAppear { self.isAnimating = true }
}
Spacer()
}
.zIndex(1)
VStack {
}
.frame(width: geo.size.width, height: geo.size.height * 0.8, alignment: .leading)
.background(Color.white)
.cornerRadius(40)
}
.frame(width: geo.size.width, height: geo.size.height, alignment: .leading)
.cornerRadius(40)
}
}
And here is the (hilarious) output
任何帮助将不胜感激!
【问题讨论】: