如何在 LazyVGrid 中将 50 个缩略图与相应的全尺寸壁纸连接起来? (Xcode 13, iOS15)

How to connect 50 thumbnails with the corresponding full size wallpapers in a LazyVGrid? (Xcode 13, iOS15)

使用带有 LazyVGrid 的完整 2960x1440 壁纸不是一种选择,因为它会导致性能不尽如人意,即使在 iPhone 12 Pro 上也是如此。

所有资产都存储在资产目录中。 这些是模型:

struct Thumbnail: Identifiable {
    var id = UUID()
    var name: String
}

struct Wallpaper: Identifiable {
    var id = UUID()
    var name: String
}

let thumbnailSet = (1...50).map { Thumbnail(name: "thumbnail-\([=12=])") }
let wallpaperSet = (1...50).map { Wallpaper(name: "wallpaper-\([=12=])") }

图库是一个简单的两列网格:

import SwiftUI

struct GalleryView: View {
    @State private var fullScreen = false
    let columns = [
        GridItem(.flexible(), spacing: 2),
        GridItem(.flexible())]
    
    var body: some View {
        ZStack {                
            // GRID VIEW
            ScrollView(showsIndicators: false) {
                VStack {
                    LazyVGrid(columns: columns, spacing: 2) {
                        ForEach(thumbnailSet.indices) { index in
                            
                            Image(thumbnailSet[index].name)
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                                .onTapGesture {(fullScreen = true)}
                        }
                    }
                }
            }
            .ignoresSafeArea()
            
            // FULL SCREEN VIEW
            if fullScreen {
                ZStack {
                    
                    // Code to show corresponding wallpaper?
                    
                    // BACK TO GRID VIEW
                    Button(action: {                            
                        (fullScreen = false)                            
                    }) {Image(systemName: "chevron.left")
                            .font(.system(size: 23))
                            .frame(width: 48, height: 44)
                    }
                    .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
                }
                .zIndex(1)
            }
        }
    }
}

这可行吗?想法?

谢谢!

您可以将 fullscreen 设为可选索引并使用它来切换和显示相应的墙纸图片:

编辑:现在有动画

struct GalleryView: View {
    @State private var fullScreen: Int? = nil // make it an optional index
    
    @Namespace var namespace
    
    let columns = [
        GridItem(.flexible(), spacing: 2),
        GridItem(.flexible())]
    
    var body: some View {
        ZStack {
            // GRID VIEW
            ScrollView(showsIndicators: false) {
                VStack {
                    LazyVGrid(columns: columns, spacing: 2) {
                        ForEach(thumbnailSet.indices) { index in
                            
                            let fullscreenIndex = fullScreen ?? -1
                            if index == fullscreenIndex {
                                Color.white
                            } else {
                            Image(thumbnailSet[index].name)
                                .resizable()
                                .aspectRatio(1, contentMode: .fill)
                                .clipped()
                                .matchedGeometryEffect(id: index, in: namespace)
                            
                                .onTapGesture {
                                    withAnimation {
                                        fullScreen = index  // set index here
                                    }
                                }
                            }
                        }
                    }
                }
            }
            .ignoresSafeArea()
            // FULL SCREEN VIEW
            if let fullscreenIndex = fullScreen {
                ZStack {
                    
                    Color.white
                        .ignoresSafeArea()
                    
                    // show image based on set index
                    Image(wallpaperSet[fullscreenIndex].name)
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .matchedGeometryEffect(id: fullscreenIndex, in: namespace)

                    // BACK TO GRID VIEW
                    Button(action: {
                        withAnimation {
                            fullScreen = nil
                        }
                    }) {Image(systemName: "chevron.left")
                            .font(.system(size: 23))
                            .frame(width: 48, height: 44)
                    }
                    .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
                }
                .zIndex(1)
            }
        }
    }
}