我在SwiftUI中遇到了一个问题,动画似乎无法在ScrollView中按预期工作。我已经创建了一个最小的、可重复的示例,其中包含一个消息列表,当添加新消息时,我希望滚动到列表的底部,并显示平滑的动画。然而,动画并不一致或平滑地发生。什么可能导致这个问题,我如何解决它?
我有一个SwiftUI视图,其中包含一个ScrollView,其中包含在类似聊天界面中显示的消息列表。当新邮件添加到列表中时,我希望视图自动滚动到底部以显示最新邮件。为了实现这一点,我使用了onChange修饰符沿着proxy.scrollTo方法, Package 在一个withAnimation块中。但是,动画并不始终按预期工作。
import SwiftUI
struct ContentView: View {
@State private var chats = ["Message 1", "Message 2", "Message 3"]
var body: some View {
VStack {
ScrollViewReader { proxy in
ScrollView {
ForEach(chats, id: \.self) { message in
Text(message)
.padding()
.id(message)
.onChange(of: chats.count) { newCount in
if newCount > 0 {
withAnimation(.easeInOut(duration: 1.0)) {
proxy.scrollTo(chats.indices.last, anchor: .bottom)
}
}
}
}
}
}
}
}
}
1条答案
按热度按时间zpf6vheq1#
我无法在运行iPadOS 16.6.1(目前最新发布的版本)的iPad上重现您的问题。
也就是说,我在您的代码中看到了一个真实的的bug和一个可能也会给您带来问题的可疑内容。
真实的的bug是使用
.id(message)
标记每个Text
,其中message
是String
。但是你说proxy.scrollTo(chats.indices.last, ...)
,其中chats.indices.last
是Int
。所以你的滚动目标永远不会被代理找到。有问题的是,您将
onChange
修饰符附加到每个Text
。如果有100条消息,您需要所有100条消息来运行onChange
闭包吗?答:没有。尝试将onChange
修改器附加到ScrollView
中的单个视图。我会将所有的Text
封装在一个VStack
中,并将onChange
连接到VStack
,如下所示: