SwiftUI animation/transition 在滚动视图中表现异常
SwiftUI animation/transition within scrollview behaving strange
我在 SwiftUI 中有一个包含多个元素的 ScrollView,其中一些会在点击时展开。
struct ExpandingView: View {
@State var showContent = false
var body: some View {
VStack {
HStack {
Button(action: {withAnimation {
self.showContent.toggle()
}
}) {
Image(systemName: "chevron.right.circle")
}
Text("TITLE")
.padding(.leading, 10)
Spacer()
}
if showContent {
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras volutpat dapibus ante eget laoreet. Aenean lacus elit, auctor ut nisl id, fermentum pretium mi. Quisque lacus nisl, suscipit hendrerit est sed, congue dictum augue. Suspendisse semper viverra accumsan. Maecenas commodo turpis convallis nisl bibendum pharetra.")
.transition(AnyTransition.move(edge: .top).combined(with: .opacity))
}
}
}
}
struct Test: View {
var body: some View {
ScrollView {
ExpandingView()
ExpandingView()
ExpandingView()
Text("Some static text")
}
}
}
如果您尝试打开其中一个扩展文本,您会发现过渡并不流畅,有点像跳跃然后开始过渡。
https://media.giphy.com/media/cjhClEVwgsEQpkBGAv/giphy.gif
所以这是我尝试过的:
- 如果我删除滚动视图并将其放入 VStack,例如它工作正常,但这不是一个选项,因为我有更多的元素不适合屏幕。
- 我曾尝试为滚动视图设置动画,因为我读到它可以解决此类问题,如下所示:
ScrollView {
ExpandingView()
ExpandingView()
ExpandingView()
Text("Some static text")
}.animation(.spring())
它在打开过渡方面工作得很好,它甚至在 spring 效果下看起来更好,但是整个滚动视图的 spring 动画在视图出现时播放,我没有不想。
https://media.giphy.com/media/lTMG9mGD0X0qrksYtB/giphy.gif
同样,如果我将 ScrollView 更改为 VStack,动画不会在出现时播放,这很好,但我必须使用滚动视图。所以对我来说最好的解决方案是保留打开文本的动画,但在视图出现时以某种方式删除它。
这是可能的解决方案。另请阅读内联评论。使用 Xcode 11.4 / ISO 13.4
测试
struct ExpandingView: View {
@State var showContent = false
var body: some View {
VStack {
HStack {
Button(action: {
self.showContent.toggle()
}) {
Image(systemName: "chevron.right.circle")
}
Text("TITLE")
.padding(.leading, 10)
Spacer()
}
if showContent {
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras volutpat dapibus ante eget laoreet. Aenean lacus elit, auctor ut nisl id, fermentum pretium mi. Quisque lacus nisl, suscipit hendrerit est sed, congue dictum augue. Suspendisse semper viverra accumsan. Maecenas commodo turpis convallis nisl bibendum pharetra.")
.fixedSize(horizontal: false, vertical: true)
.transition(AnyTransition.move(edge: .top).combined(with: .opacity))
}
}
}
}
struct DemoExpandingView: View {
// initial nil to avoid initial animation
@State private var animation: Animation? = nil
var body: some View {
ScrollView {
VStack {
ExpandingView()
ExpandingView()
ExpandingView()
Text("Some static text")
}.animation(animation) // << needed to animate static section
}
.onAppear {
DispatchQueue.main.async {
// assign in-container animation `after` container rendered
self.animation = .default
}
}
}
}
我在 SwiftUI 中有一个包含多个元素的 ScrollView,其中一些会在点击时展开。
struct ExpandingView: View {
@State var showContent = false
var body: some View {
VStack {
HStack {
Button(action: {withAnimation {
self.showContent.toggle()
}
}) {
Image(systemName: "chevron.right.circle")
}
Text("TITLE")
.padding(.leading, 10)
Spacer()
}
if showContent {
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras volutpat dapibus ante eget laoreet. Aenean lacus elit, auctor ut nisl id, fermentum pretium mi. Quisque lacus nisl, suscipit hendrerit est sed, congue dictum augue. Suspendisse semper viverra accumsan. Maecenas commodo turpis convallis nisl bibendum pharetra.")
.transition(AnyTransition.move(edge: .top).combined(with: .opacity))
}
}
}
}
struct Test: View {
var body: some View {
ScrollView {
ExpandingView()
ExpandingView()
ExpandingView()
Text("Some static text")
}
}
}
如果您尝试打开其中一个扩展文本,您会发现过渡并不流畅,有点像跳跃然后开始过渡。
https://media.giphy.com/media/cjhClEVwgsEQpkBGAv/giphy.gif
所以这是我尝试过的:
- 如果我删除滚动视图并将其放入 VStack,例如它工作正常,但这不是一个选项,因为我有更多的元素不适合屏幕。
- 我曾尝试为滚动视图设置动画,因为我读到它可以解决此类问题,如下所示:
ScrollView {
ExpandingView()
ExpandingView()
ExpandingView()
Text("Some static text")
}.animation(.spring())
它在打开过渡方面工作得很好,它甚至在 spring 效果下看起来更好,但是整个滚动视图的 spring 动画在视图出现时播放,我没有不想。
https://media.giphy.com/media/lTMG9mGD0X0qrksYtB/giphy.gif
同样,如果我将 ScrollView 更改为 VStack,动画不会在出现时播放,这很好,但我必须使用滚动视图。所以对我来说最好的解决方案是保留打开文本的动画,但在视图出现时以某种方式删除它。
这是可能的解决方案。另请阅读内联评论。使用 Xcode 11.4 / ISO 13.4
测试struct ExpandingView: View {
@State var showContent = false
var body: some View {
VStack {
HStack {
Button(action: {
self.showContent.toggle()
}) {
Image(systemName: "chevron.right.circle")
}
Text("TITLE")
.padding(.leading, 10)
Spacer()
}
if showContent {
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras volutpat dapibus ante eget laoreet. Aenean lacus elit, auctor ut nisl id, fermentum pretium mi. Quisque lacus nisl, suscipit hendrerit est sed, congue dictum augue. Suspendisse semper viverra accumsan. Maecenas commodo turpis convallis nisl bibendum pharetra.")
.fixedSize(horizontal: false, vertical: true)
.transition(AnyTransition.move(edge: .top).combined(with: .opacity))
}
}
}
}
struct DemoExpandingView: View {
// initial nil to avoid initial animation
@State private var animation: Animation? = nil
var body: some View {
ScrollView {
VStack {
ExpandingView()
ExpandingView()
ExpandingView()
Text("Some static text")
}.animation(animation) // << needed to animate static section
}
.onAppear {
DispatchQueue.main.async {
// assign in-container animation `after` container rendered
self.animation = .default
}
}
}
}