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

如何为ScrollView/LazyVGrid中API获取的数据添加动画效果?

解决方案:实现数据加载时的流畅动画效果

一、修正数据加载时机,确保首次视图出现即触发请求

当前.task附加在LazyVGrid上,首次打开时LazyVGrid可能还未完成渲染,导致请求触发延迟或动画不同步。将加载任务移到ScrollView层级,确保视图出现就执行数据请求:

ScrollView {
    // ... 原有内容
}
.task {
    if selectedSegmentedOption == .myPresentations {
        await viewModel.getAllPresentations(page: 1, pageSize: 10)
    }
}
.background(CustomColor.background.swiftUIColor)

二、在ViewModel中用withAnimation包裹数据更新

确保数据更新时通知SwiftUI触发动画,修改PresentationsViewModel中的getAllPresentations方法:

func getAllPresentations(page: Int, pageSize: Int) async {
    // ... 原有数据请求逻辑
    let fetchedData = // 从接口获取的数据
    withAnimation {
        self.myPresentations = fetchedData
        self.shouldShowEmptyScreen = fetchedData.isEmpty
    }
}

三、给列表项添加入场动画

修改PresentationRootView中的LazyVGrid,为每个列表项添加过渡动画:

LazyVGrid(columns: columns, spacing: 4, content: {
    ForEach($viewModel.myPresentations, id: \.ID) { element in
        PresentationSingleView(url: element.ThumbURLWithSas.wrappedValue, title: element.Name.wrappedValue, numberOfResources: 4)
            .padding([.leading, .trailing], 13)
            .transition(.opacity.combined(with: .scale)) // 添加过渡动画
    }
})

四、优化图片加载的过渡动画

在PresentationSingleView中,给图片添加平滑的显示过渡,同时添加占位图保持布局稳定:

// 替换原来的image.view?部分
Group {
    if let imageView = image.view {
        imageView
            .resizable()
            .scaledToFill()
            .frame(maxWidth: isIphone ? 90 : 140, maxHeight: isIphone ? 64 : 140)
            .cornerRadius(4)
            .padding(isIphone ? 10 : 20)
            .transition(.opacity) // 图片加载完成的过渡
    } else {
        // 加载占位图
        Color.gray.opacity(0.2)
            .frame(maxWidth: isIphone ? 90 : 140, maxHeight: isIphone ? 64 : 140)
            .cornerRadius(4)
            .padding(isIphone ? 10 : 20)
    }
}
.animation(.easeInOut(duration: 0.3), value: image.view)

五、处理空视图的切换动画

给空视图和列表的切换添加过渡,避免生硬跳转:

ScrollView {
    if selectedSegmentedOption == .myPresentations {
        if viewModel.shouldShowEmptyScreen {
            Text("No data")
                .transition(.opacity)
        } else {
            LazyVGrid(columns: columns, spacing: 4, content: {
                // ... 原有列表项内容
            })
            .transition(.opacity.combined(with: .slide))
        }
    }
}
.animation(.easeInOut(duration: 0.3), value: viewModel.shouldShowEmptyScreen)

关键前提

确保myPresentations是ViewModel中的@Published属性,这样数据变化才能正确通知View更新:

class PresentationsViewModel: ObservableObject {
    @Published var myPresentations: [YourModelType] = []
    @Published var shouldShowEmptyScreen = true
    // ... 其他代码
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 07:15:57