我的
TabView
正在由一系列 Identifiable
项目填充。如果数组大小以将当前可见项目保留在屏幕上的方式增大或缩小,则视图会给我带来尴尬的闪烁动画。看起来像是从一个视图转换到另一个视图,即使视图、id 和演示文稿是相同的
有人知道如何停止动画吗?
我尝试过以下各种组合:
.id()
、TabView
和内容视图上显式设置
ForEach
.transition(.identity)
.animation(nil)
但一切都无济于事
struct Item: Identifiable, Equatable {
let id: Int
let color: Color
}
struct ContentView: View {
@Namespace var animation
@State var items: [Item] = []
var body: some View {
VStack {
TabView {
ForEach(items, id:\.id) { item in
item.color
}
}
.background(Color.red)
.tabViewStyle(.page)
.frame(width: 300, height: 300)
HStack {
Button("State 1") {
self.items = [
.init(id: 0, color: .green),
.init(id: 1, color: .blue)
]
}
Button("State 2") {
self.items = [
.init(id: 0, color: .green),
.init(id: 1, color: .blue),
.init(id: 2, color: .purple)
]
}
}
}
.padding()
}
}
所以,我很高兴告诉您我能够通过一些技巧解决您的闪烁问题。首先,我使用 ZStack 嵌入 TabView 并在其顶部放置您在 TabView 中渲染的最后一种颜色的项目,其不透明度可以是 0 或 1,具体取决于状态是否正在更改。 我使用 TabView 的选择属性跟踪最后一种颜色。 这是代码:
@Namespace var animation
@State private var currentItem: Color = .green
@State private var isAboutToChange = false
@State var items: [Item] = []
var body: some View {
VStack {
ZStack {
TabView(selection: $currentItem) {
ForEach(items, id:\.id) { item in
item.color
.tag(item.color)
}
}
.background(Color.red)
.tabViewStyle(.page)
currentItem
.opacity(isAboutToChange ? 1 : 0)
.overlay(alignment: .bottom) {
RenderColorsTabView()
}
}
.frame(width: 300, height: 300)
HStack {
Button("State 1") {
isAboutToChange = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
self.items = [
.init(id: 0, color: .green),
.init(id: 1, color: .blue)
]
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
isAboutToChange = false
}
}
Button("State 2") {
isAboutToChange = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
self.items = [
.init(id: 0, color: .green),
.init(id: 1, color: .blue),
.init(id: 2, color: .purple)
]
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
isAboutToChange = false
}
}
}
}
.padding()
}
@ViewBuilder
func RenderColorsTabView() -> some View{
TabView(selection: $currentItem) {
ForEach(items, id:\.id) { item in
item.color
.tag(item.color)
}
}
.tabViewStyle(.page)
}
你怎么看我需要一个布尔标志来注意到变化何时即将发生,这样我就可以将虚拟颜色的不透明度切换到 1 几分之一秒,这样闪烁就被隐藏了。另一个技巧是重用 TabView,通过在其底部显示点来使虚拟项目视图看起来真实。 我希望对您有所帮助!如果您有任何疑问,请告诉我。