2.3 C
New York
Wednesday, February 5, 2025

ios – LazyVGrid merchandise hit check space isn’t anticipated


I’m studying SwiftUI and making an attempt to impl a photograph gallery app, utilizing LazyVGrid.
Within the ForEach loop of my ContentView’s physique() methodology, I’ve a thumbnail view for every photograph fetched from the library.

import SwiftUI
import Photographs
import CoreImage
import ImageIO
import AVKit
import AVFoundation

struct Content material: Identifiable {
    let id = UUID()
    let phAsset: PHAsset
    let index: Int
}

struct ContentView: View {
    @State non-public var contents: [Content] = []
    @State non-public var selectedContent: Content material? = nil
    @State non-public var isLoading: Bool = true

    var physique: some View {
        NavigationView {
            let minItemWidth: CGFloat = 100
            let spacing: CGFloat = 2
            let screenWidth = UIScreen.foremost.bounds.width
            let columns = Int((screenWidth + spacing) / (minItemWidth + spacing))
            let totalSpacing = spacing * CGFloat(columns - 1)
            let itemWidth = (screenWidth - totalSpacing) / CGFloat(columns)
            ZStack {
                ScrollView {
                    LazyVGrid(columns: [GridItem(.adaptive(minimum: 100))], spacing: 2) {
                        ForEach(contents) { content material in
                            ThumbnailView(content material: content material.phAsset)
                                .body(width: itemWidth, peak: itemWidth)
                                .onTapGesture {
                                    selectedContent = content material
                                }
                                .padding(4)
                                .background(Colour.blue.opacity(0.5))
                                .clipped()
                        }
                    }
                    .padding(2)
                }
                .navigationTitle("Photographs Library")
                .onAppear(carry out: loadContents)
                .sheet(merchandise: $selectedContent) { content material in
                    NavigationView {
                        DetailImageView(asset: content material.phAsset)
                            .navigationBarItems(trailing: Button("Accomplished") {
                                selectedContent = nil
                            })
                    }
                }

                if isLoading {
                    ProgressView("Loading...")
                        .progressViewStyle(CircularProgressViewStyle())
                        .scaleEffect(1.5, anchor: .middle)
                }
            }
        }
    }

    func loadContents() {
        PHPhotoLibrary.requestAuthorization { standing in
            if standing == .licensed {
                fetchContents()
            }
        }
    }

    func fetchContents() {
        let fetchOptions = PHFetchOptions()

        DispatchQueue.international(qos: .background).async {
            self.isLoading = true
            let fetchResult = PHAsset.fetchAssets(with: fetchOptions)
            var fetchedContents: [Content] = []
            var index = 0
            fetchResult.enumerateObjects { (phAsset, _, _) in
                fetchedContents.append(Content material(phAsset: phAsset, index: index))
                index += 1
            }
            self.isLoading = false

            DispatchQueue.foremost.async {
                contents = fetchedContents
            }
        }
    }
}

struct ThumbnailView: View {
    let content material: PHAsset
    @State non-public var picture: UIImage? = nil

    var physique: some View {
        Group {
            if let picture = picture {
                Picture(uiImage: picture)
                    .resizable()
                    .scaledToFill()
            } else {
                Colour.grey
            }
        }
        .onAppear(carry out: loadImage)
    }

    func loadImage() {
        let imageManager = PHImageManager.default()
        let requestOptions = PHImageRequestOptions()
        requestOptions.isSynchronous = false
        imageManager.requestImage(for: content material, targetSize: CGSize(width: 100, peak: 100), contentMode: .aspectFill, choices: requestOptions) { (picture, _) in
            self.picture = picture
        }
    }
}

struct DetailImageView: View {
    let asset: PHAsset
    @State non-public var picture: UIImage?

    var physique: some View {
        Group {
            if let picture = picture {
                Picture(uiImage: picture)
                    .resizable()
                    .aspectRatio(contentMode: .match)
                    .edgesIgnoringSafeArea(.all)
            } else {
                ProgressView()
            }
        }
        .onAppear(carry out: loadFullImage)
    }

    func loadFullImage() {
        let supervisor = PHImageManager.default()
        let choices = PHImageRequestOptions()
        choices.deliveryMode = .highQualityFormat
        choices.isNetworkAccessAllowed = true

        supervisor.requestImage(
            for: asset,
            targetSize: PHImageManagerMaximumSize,
            contentMode: .aspectFit,
            choices: choices
        ) { end result, _ in
            picture = end result
        }
    }
}

The issue is that once I click on on sure space of an merchandise, the opened merchandise isn’t anticipated. I attempted debugging this concern for an entire day and located if I remark out the “.clipped()” modifier on the ThumbnailView, I can see the merchandise views of the LazyVGrid is overlapped, that’s the reason why the view on prime is opened aside from the view I believed I clicked. That is fairly unusual to me as I consider if I specify the dimensions of a view by .body() modifier, it shouldn’t be capable of obtain any contact occasion exterior the realm.

I’m new to SwiftUI and iOS programming, any assist may be very appreciated.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles