SwiftUI:列表在 HStack 中弄乱了其子视图的动画
SwiftUI: List is messing up animation for its subviews inside an HStack
我正在制作一个显示大量实时到达时间的 WatchOS 应用程序。我想在 List 的每个单元格的尾端放置一个视图,一个我设计的实时指标,将连续动画。
实时指示器视图只有两个图像,我正在连续设置其不透明度动画。这个视图本身似乎工作正常:
animated view by itself
但是,当嵌入到 List 中然后嵌入到 HStack 中时,动画似乎影响了我的动画视图的位置,而不仅仅是它的不透明度。
animated view inside a cell
这个视图移动的距离似乎只受 HStack 高度的影响。
动画查看代码:
struct RTIndicator: View {
@State var isAnimating = true
private var repeatingAnimation: Animation {
Animation
.spring()
.repeatForever()
}
private var delayedRepeatingAnimation: Animation {
Animation
.spring()
.repeatForever()
.delay(0.2)
}
var body: some View {
ZStack {
Image("rt-inner")
.opacity(isAnimating ? 0.2 : 1)
.animation(repeatingAnimation)
Image("rt-outer")
.opacity(isAnimating ? 0.2 : 1)
.animation(delayedRepeatingAnimation)
}
.frame(width: 16, height: 16, alignment: .center)
.colorMultiply(.red)
.padding(.top, -6)
.padding(.trailing, -12)
.onAppear {
self.isAnimating.toggle()
}
}
}
所有代码:
struct SwiftUIView: View {
var body: some View {
List {
HStack {
Text("Cell")
.frame(height: 100)
Spacer()
RTIndicator()
}.padding(8)
}
}
}
此处找到解决方法。测试 Xcode 12.
var body: some View {
List {
HStack {
Text("Cell")
.frame(height: 100)
Spacer()
}
.overlay(RTIndicator(), alignment: .trailing) // << here !!
.padding(8)
}
}
虽然它很老套,但我找到了解决这个问题的临时方法。它基于 Asperi 的回答。
我已经创建了一个名为 ClearView 的单独视图,它有一个动画但不渲染任何视觉效果并将其用作同一个 HStack 中的第二个整体。
struct ClearView: View {
@State var isAnimating = false
var body: some View {
Rectangle()
.foregroundColor(.clear)
.onAppear {
withAnimation(Animation.linear(duration: 0)) {
self.isAnimating = true
}
}
}
}
var body: some View {
List {
HStack {
Text("Cell")
.frame(height: 100)
Spacer()
}
.overlay(RTIndicator(), alignment: .trailing)
.overlay(ClearView(), alignment: .trailing)
.padding(8)
}
}
我正在制作一个显示大量实时到达时间的 WatchOS 应用程序。我想在 List 的每个单元格的尾端放置一个视图,一个我设计的实时指标,将连续动画。
实时指示器视图只有两个图像,我正在连续设置其不透明度动画。这个视图本身似乎工作正常:
animated view by itself
但是,当嵌入到 List 中然后嵌入到 HStack 中时,动画似乎影响了我的动画视图的位置,而不仅仅是它的不透明度。
animated view inside a cell
这个视图移动的距离似乎只受 HStack 高度的影响。
动画查看代码:
struct RTIndicator: View {
@State var isAnimating = true
private var repeatingAnimation: Animation {
Animation
.spring()
.repeatForever()
}
private var delayedRepeatingAnimation: Animation {
Animation
.spring()
.repeatForever()
.delay(0.2)
}
var body: some View {
ZStack {
Image("rt-inner")
.opacity(isAnimating ? 0.2 : 1)
.animation(repeatingAnimation)
Image("rt-outer")
.opacity(isAnimating ? 0.2 : 1)
.animation(delayedRepeatingAnimation)
}
.frame(width: 16, height: 16, alignment: .center)
.colorMultiply(.red)
.padding(.top, -6)
.padding(.trailing, -12)
.onAppear {
self.isAnimating.toggle()
}
}
}
所有代码:
struct SwiftUIView: View {
var body: some View {
List {
HStack {
Text("Cell")
.frame(height: 100)
Spacer()
RTIndicator()
}.padding(8)
}
}
}
此处找到解决方法。测试 Xcode 12.
var body: some View {
List {
HStack {
Text("Cell")
.frame(height: 100)
Spacer()
}
.overlay(RTIndicator(), alignment: .trailing) // << here !!
.padding(8)
}
}
虽然它很老套,但我找到了解决这个问题的临时方法。它基于 Asperi 的回答。
我已经创建了一个名为 ClearView 的单独视图,它有一个动画但不渲染任何视觉效果并将其用作同一个 HStack 中的第二个整体。
struct ClearView: View {
@State var isAnimating = false
var body: some View {
Rectangle()
.foregroundColor(.clear)
.onAppear {
withAnimation(Animation.linear(duration: 0)) {
self.isAnimating = true
}
}
}
}
var body: some View {
List {
HStack {
Text("Cell")
.frame(height: 100)
Spacer()
}
.overlay(RTIndicator(), alignment: .trailing)
.overlay(ClearView(), alignment: .trailing)
.padding(8)
}
}