[英]Changing icon causes a hitch in SwiftUI animation?
我有一个标签列表,当你 select 时,它们会出现一个芯片。
当您单击每个芯片上的“X”时,标签应滑出一个 animation,列表中的标签将被标记为未选中。
我遇到的问题是当我移除最后一个芯片时,标签左侧的圆形/圆形检查与 animation 不顺畅流动。
我相信这是因为图标在选择与未选择时会发生变化,因为如果我保持图标相同,这不是问题。 如果我移除芯片上的幻灯片 animation 也不是问题,但是我喜欢这个 animation 并想保留它。
我实际上在我的应用程序的几个地方遇到了这个问题,涉及动画+更改图标,并且想知道是否有解决方法?
我在下面附上了一个可重现的例子。
import SwiftUI
struct ContentView: View {
var body: some View {
Icon_Animation()
}
}
struct Icon_Animation: View {
//All tags
var testTags: [Tag] =
[Tag("tag1"),
Tag("tag2"),
Tag("tag3")]
//Only tags that have been selected
@State var selectedTags = [Tag]()
var body: some View {
ScrollView{
//Hstack of the tags that have been selected
HStack{
ForEach(selectedTags){ tag in
HStack(spacing: 0){
Button{
//Clicking on the X will remove from selectedTags array, and then make that tag's isSelected = false
withAnimation(.easeOut) {
if let index = selectedTags.firstIndex(where: {$0.name == tag.name}){
selectedTags.remove(at: index)
}
}
//PROBLEM: even though this statemnt isn't in the withAnimation block, it causes a weird behavior with the circle/check-circle icon
//If I remove the withAnimation statement from the above block, it works fine. However, I would like to keep the slide animation on the chips.
tag.isSelected = false
}label:{
Image(systemName: "x.circle.fill")
.font(.subheadline)
.padding(.horizontal, 6)
}
Image(systemName: "number")
.font(.footnote.weight(.bold))
.padding(.trailing, 2)
Text("\(tag.name)")
.font(.footnote)
}
.padding(.trailing, 20)
.padding(.vertical, 6)
.background(Color.blue.opacity(0.6), in: RoundedRectangle(cornerRadius: 14, style: .continuous))
.transition(.slide)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
//List of tags where you can select each tag to create a chip
ForEach(testTags){ tag in
TagView(tag: tag)
.onTapGesture {
tag.isSelected.toggle()
if(tag.isSelected == true){
selectedTags.append(tag)
}
}
}
.padding()
}
.padding()
}
}
class Tag: Identifiable, ObservableObject {
var id = UUID()
@Published var name: String
@Published var isSelected = false
init(_ name: String){
self.name = name
}
}
struct TagView: View {
@ObservedObject var tag: Tag = Tag("test")
var body: some View {
ZStack{
//Overlay for when tag is selected
Rectangle()
.fill(Color.purple.opacity(0.6))
.edgesIgnoringSafeArea(.all)
.cornerRadius(5)
.opacity(tag.isSelected ? 1 : 0)
HStack(spacing: 8){
//PROBLEM!!: I want to use a different icon based on whether tag isSelected, but it's causing a hitch in the animation when switching
if(tag.isSelected){
Image(systemName: "checkmark.circle.fill")
.font(.title2.weight(.light))
}else{
Image(systemName: "circle")
.font(.title2.weight(.light))
}
Image(systemName: "number")
.font(.body.weight(.bold))
Text(tag.name)
.font(.headline)
.fontWeight(.bold)
}
.frame(maxWidth: .infinity, alignment: .leading)
}
}
}
我认为这是一个常见问题,归结为父视图从 if 语句接收两个不同的子视图,并且由于它们是两个不同的视图,具有不同的 id,SwiftUI 不知道如何在它们之间设置动画。
诀窍是只使用一个内容可变的子视图。 您应该能够通过替换生成图像的TagView
中的if...else...
来实现这一点,并在初始化程序中使用三元组:
Image(systemName: tag.isSelected ? "checkmark.circle.fill" : "circle" )
.font(.title2.weight(.light))
问题未解决?试试以下方法:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.