首页 > 解决方案 > 如何使用来自 url 的图像平滑滚动?

问题描述

我想做一个无限滚动的帖子视图。我正在使用 ScrollView + LazyVStack(如果我使用 List,那么行为是相同的)。此示例中的 Row 类似于我的实际项目中的 Row - 文本,然后是图片,然后是垂直堆栈中的更多文本。问题是当我滚动时,当图片出现时,开始抽搐。我注意到,如果你只留下图片并移除 VStack,那么抽搐就会减少,但它们仍然存在。在这个例子中,我使用的是来自 ios 15 的 AsyncImage,但对于来自 Nuke、SDWebImage 和其他的图片的行为相同。如何在不抽搐的情况下平滑滚动?

import SwiftUI

struct ContentView: View {
    
    let urls: [URL] = [
        URL(string: "https://klike.net/uploads/posts/2019-05/1556945414_2.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426537_1.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426563_6.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426524_3.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426502_5.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426571_23.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426508_4.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426506_2.jpg")!,
        URL(string: "https://klike.net/uploads/posts/2018-12/1544426569_9.jpg")!
    ]
    
    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(urls, id: \.self) { url in
                    Row(url: url)
                }
            }
        }
    }
}

struct Row: View {
    let url: URL
    let width = UIScreen.main.bounds.width
    
    var body: some View {
        VStack(spacing: 0) {
            Text(url.absoluteString)
                .font(.body)
            
            // Here can be Nuke, SDWebImage or something else
            AsyncImage(url: url) { image in
                image
                    .resizable()
                    .scaledToFit()
            } placeholder: {
                ProgressView()
            }
            .frame(width: width, height: width * 1.666666666666667) // <- 800/480 image size
            
            Text(url.absoluteString)
                .font(.callout)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

标签: swiftui

解决方案


当用户滚动时,每次可见一行时,应用程序都会重复请求相同的图像。因此,我相信您需要缓存下载的图像。


推荐阅读