You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中卡片Image在动画交互时闪烁问题求助

SwiftUI卡片中Image交互时闪烁问题求助

在SwiftUI开发中,我遇到一个问题:简单VStack卡片上的Image在交互过程中会出现闪烁现象。我已将问题从项目中抽离,制作了简化示例:通过按钮唤起PhotoPicker选择照片并添加到状态中,每张照片卡片用ObservableObject跟踪选中状态——点击切换选中,确保同一时间仅一张卡片被选中。

示例代码

class EntriesState : ObservableObject {
    @Published var selectedIndex : Int? = nil
}

struct PhotoView : View {
    var image : Data;
    var index : Int;
    @ObservedObject var entriesState: EntriesState
    
    var body: some View {
        VStack {
            if let uiImage = UIImage(data: image) {
                Image(uiImage: uiImage)
                    .resizable()
                    .scaledToFit()
                    .clipShape(RoundedRectangle(cornerRadius: 24.0))
                    .onAppear() {
                        print("Image \(index) appeared")
                    }
            }
            if entriesState.selectedIndex == index {
                Text("This is the description for the image")
            }
        }
        .padding(20)
        .background(Color.blue)
        .clipShape(RoundedRectangle(cornerRadius: 24.0))
        .onTapGesture {
            // 移除withAnimation可解决闪烁,但会丢失卡片展开/收缩动画
            // 有没有办法保留动画同时避免Image闪烁?
            withAnimation {
                if entriesState.selectedIndex == index {
                    entriesState.selectedIndex = nil
                } else {
                    entriesState.selectedIndex = index
                }
            }
        }
    }
}

struct ContentView: View {
    @State private var selectedItems = [PhotosPickerItem]()
    @State private var selectedImages = [Data]()
    @StateObject var entriesState = EntriesState()

    var body: some View {
        NavigationStack {
            ScrollView {
                LazyVGrid(columns: [GridItem(.adaptive(minimum: 200))]) {
                    ForEach(0..<selectedImages.count, id: \.self) { i in
                        PhotoView(image: selectedImages[i], index: i, entriesState: entriesState)
                            .padding(20)
                    }
                }
            }
            .toolbar {
                PhotosPicker("Select images", selection: $selectedItems, matching: .images)
            }
            .onChange(of: selectedItems) {
                Task {
                    selectedImages.removeAll()

                    for item in selectedItems {
                        if let data = try? await item.loadTransferable(type: Data.self) {
                            selectedImages.append(data)
                        }
                    }
                }
            }
        }
    }
}

已尝试的解决方案

  • 使用@Binding替代@ObservableObject跟踪选中索引
  • 为Image添加.id(index)修饰符
  • 跟踪Image的.onAppear调用——仅触发一次,不符合重新渲染预期
  • 移除动画:可解决闪烁,但丢失卡片展开/收缩动画效果
  • 在PhotoView中使用@State var selected:阻止了所有Image闪烁,但选中的卡片仍会闪烁
  • 在StackOverflow和Google搜索类似问题,未找到有效解决办法

恳请各位提供建议或解决方案,谢谢!

内容的提问来源于stack exchange,提问作者Mark Schmidt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 00:27:39