如何在 LazyVGrid 中以编程方式触发 NavigationLink

Mis*_*cha 2 lazy-loading swiftui swiftui-navigationlink lazyvgrid

我有一个LazyVGrid里面的NavigationView

NavigationView {
    ScrollView {
        LazyVGrid(columns: columns) {
            ForEach(items) { item in
                NavigationLink(tag: item, selection: $displayedItem) {
                    DetailView(item)
                } label: {
                    GridItemView(item)
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

引用的变量在视图上定义如下:

@State var displayedItem: Item?
let columns: [GridItem] = Array(repeating: .init(.flexible()), count: 2)
Run Code Online (Sandbox Code Playgroud)

现在我想显示特定项目的详细视图。我通过简单地将此项分配给displayedItem属性来做到这一点:

func showDetailView(for item: Item) {
    displayedItem = item
}
Run Code Online (Sandbox Code Playgroud)

LazyVGrid当我调用此函数时相应项目可见时,这非常有效。但是,当该项目不可见时,我首先需要滚动到该项目才能NavigationLink触发。我知道为什么会发生这种情况(因为项目是延迟加载的,毕竟它是一个惰性LazyVGrid网格),但我不知道如何在需要时加载特定项目。


我尝试过的:

我还尝试通过将整个内容包装ScrollView在 a 内ScrollViewReader并附加以下修饰符以编程方式滚动到目标项目:

.onChange(of: displayedItem) { item in
    if let item = item {
        scrollProxy.scrollTo(item.id)
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这也存在同样的问题:在加载项目之前,滚动到给定项目不起作用。


问题:

有什么方法可以实现此功能,即触发NavigationLink当前在 中不可见的项目LazyVGrid?(这对我来说很重要,因为我需要此功能来深层链接到特定项目的DetailView。)

Asp*_*eri 6

一种可能的方法可以像本主题中那样- 使用 ScrollView 背景中某处的一个链接,并通过用户的点击手势/按钮或以编程方式分配相应的值来激活它。

使用 Xcode 13.4 / iOS 15.5 进行测试

在此输入图像描述

主要部分:

ScrollView {
    LazyVGrid(columns: columns) {
        ForEach(items) { item in
            RoundedRectangle(cornerRadius: 16).fill(.yellow)
                .frame(maxWidth: .infinity).aspectRatio(1, contentMode: .fit)
                .overlay(Text("Item \(item.value)"))
                .onTapGesture {
                    selectedItem = item
                }
        }
    }
}
.padding(.horizontal)
.background(
    NavigationLink(destination: DetailView(item: selectedItem), isActive: isActive) {
        EmptyView()
    }
)
.toolbar {
    Button("Random") { selectedItem = items.randomElement() }
}
Run Code Online (Sandbox Code Playgroud)

GitHub 上的测试模块