繁体   English   中英

更改图标会导致 SwiftUI animation 出现故障?

[英]Changing icon causes a hitch in SwiftUI animation?

我有一个标签列表,当你 select 时,它们会出现一个芯片。

当您单击每个芯片上的“X”时,标签应滑出一个 animation,列表中的标签将被标记为未选中。

我遇到的问题是当我移除最后一个芯片时,标签左侧的圆形/圆形检查与 animation 不顺畅流动。

我相信这是因为图标在选择与未选择时会发生变化,因为如果我保持图标相同,这不是问题。 如果我移除芯片上的幻灯片 animation 也不是问题,但是我喜欢这个 animation 并想保留它。

我实际上在我的应用程序的几个地方遇到了这个问题,涉及动画+更改图标,并且想知道是否有解决方法?

动画问题的GIF

我在下面附上了一个可重现的例子。

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))

问题未解决?试试以下方法:

更改图标会导致 SwiftUI animation 出现故障?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2023 STACKOOM.COM