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

Viewed 157

Using the full, 2960x1440 wallpapers with LazyVGrid is not an option, as it leads to unsatisfactory performance, even on an iPhone 12 Pro.

All assets are stored in the asset catalog. These are the Models:

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-\($0)") }
let wallpaperSet = (1...50).map { Wallpaper(name: "wallpaper-\($0)") }

The gallery is a simple two column grid:

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

Is this doable? Ideas?

Thank you!

1 Answers

You can make your fullscreenan optional index and use that to switch and show the respective wallpaper image:

EDIT: now with animation

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