您如何判断用户何时滚动到 LazyVGrid 的底部?
Posted
技术标签:
【中文标题】您如何判断用户何时滚动到 LazyVGrid 的底部?【英文标题】:How do you tell when the user has scrolled to the bottom of a LazyVGrid? 【发布时间】:2021-10-07 01:00:53 【问题描述】:我对 SwiftUI 还很陌生,我正在尝试找出一个我似乎无法解决的问题。我正在构建一个基于 GitHub API 的应用程序。在其中一个屏幕中,我显示了特定用户拥有的所有关注者。
我想要完成的是,我想知道用户何时滚动到关注者列表的底部,因为我目前只从服务器获取 100 条记录。
我如何知道用户何时滚动到这 100 个关注者的底部,以便我可以在第二页和后续页面中发起另外 100 条记录的请求?
我在 google 上搜索过,看到了有关 ScrollViewReader、GeometryReader 的信息,但我不知道如何解决这个问题。这是此特定屏幕中的代码:
import SwiftUI
struct FollowersScreen: View
@EnvironmentObject var savedFavorites: SavedFavorites
@State var userID: String
@State private var isPresented = false
@State private var followers: [Follower] = []
@State private var page = 1
@State private var user: User? = nil
let columns = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())]
var body: some View
VStack
ScrollView
LazyVGrid(columns: columns, content:
ForEach(followers, id: \.self) follower in
FollowerCell(follower: follower)
.onAppear(perform:
// What do I do here to get 100 more records properly?
)
.onTapGesture
self.getFollowerDetails(userID: follower.login)
// ON TAP GESTURE
// FOR EACH
)// LAZYVGRID
.padding(.horizontal)
// SCROLL VIEW
// VSTACK
.onAppear(perform:
self.getFollowers(userID: userID, page: 1)
)
.navigationTitle("\(userID) Followers")
.navigationBarTitleDisplayMode(.inline)
.navigationBarItems(trailing:
Button(action:
addFavourite(gitHubUser: userID)
)
Image(systemName: Images.heartCircle)
.resizable()
.scaledToFit()
.frame(width: 33, height: 33, alignment: .center)
)// NAV BAR ITEMS
.sheet(isPresented: $isPresented, onDismiss: nil)
FollowersDetailScreen(gitHubUser: $userID, isPresented: $isPresented, followers: $followers, user: user)
.environmentObject(savedFavorites)
// BODY
private func getFollowers(userID: String, page: Int)
NetworkManager.shared.getFollowers(for: userID, page: page) result in
switch result
case .success(let followers):
self.followers += followers
print("**** Count of Followers: \(self.followers.count)")
case .failure(let error):
print("getFollowers(gitHubUser:, page:) -> Error: \(error)")
private func getFollowerDetails(userID: String)
NetworkManager.shared.getUserInfo(for: userID) result in
switch result
case .success(let user):
print("Success, found the user info!")
self.user = user
guard let tempUser = self.user else return
print(tempUser)
self.isPresented = true
case .failure(let error):
print("getUser(gitHubUser:, page:) -> Error: \(error)")
private func addFavourite(gitHubUser: String)
NetworkManager.shared.getUserInfo(for: gitHubUser) result in
switch result
case .success(let user):
let favorite = Follower(login: user.login, avatarUrl: user.avatarUrl)
savedFavorites.favorites.append(favorite)
PersistenceManager.shared.encodeJSONToDisk(favorites: savedFavorites.favorites)
case .failure(let error):
print("getFavourite(gitHubUser:, page:) -> Error: \(error)")
struct FollowersScreen_Previews: PreviewProvider
static var previews: some View
FollowersScreen(userID: "sallen0400")
【问题讨论】:
要回答您的问题,您需要处理GeometryReader
,当我们处于所有关注者的底部时,它需要一些行代码来通知,但这是不必要的,因为LazyVGrid
足够聪明调用所需的数据!你不应该关心它!如果没有 LazyVGrid 存在,你会做这样的事情!
抱歉,您的评论完全不清楚。
你的意思是完全不清楚?
是的,如果您能描述更容易理解的步骤。
【参考方案1】:
你不需要知道你什么时候在LazyVGrid
的底部,你需要知道你什么时候数据用完了。您需要您在列表中的位置的索引,并将其与数组的计数进行比较。另外,我不得不使用一些伪代码,因为我没有你所有的类型:
LazyVGrid(columns: columns, content:
// Zip gives you both the index and the item. You could just get the index, but the
// code reads better this way, IMHO
ForEach(Array(zip(followers.indices, followers), id: \.1) index, follower in
FollowerCell(follower: follower)
.onAppear(perform:
// Now we test our index against the total array count.
// You should also build a check that once you get an end of
// data response that you don't keep calling for more data.
if followers.count()/* - buffer*/ == index // Place buffer here for earlier update.
getFollowers(userID: ...
)
.onTapGesture
self.getFollowerDetails(userID: follower.login)
// ON TAP GESTURE
// FOR EACH
)// LAZYVGRID
当我最初回答这个问题时,我在调用更新之前建立了一个包含 20 个项目的缓冲区。然而,通过进一步的实验,我发现这不是必需的,因为.onAppear
在视图实际出现在屏幕上之前就被触发了。如果您想添加一个缓冲区以便有更多时间下载数据,您所要做的就是从总计数中减去给定数量的项目,以便更早触发更新。我对它的放置位置发表了评论。
【讨论】:
已编辑以更正ForEach
中的id:
。
感谢您的评论!我会尝试并报告!
它似乎工作.. 谢谢!
那么,zip 方法只允许您将索引附加到关注者数组中的特定项目?这是一个聪明的主意!
它本质上创建了一个元组数组。一个是数组的元素,一个是它的索引。对id:
的编辑是告诉ForEach
以元素的id 为基础,而不是索引。请参阅this answer 以获得更完整的解释。我在遇到.enumerated
的问题时偶然发现了它。以上是关于您如何判断用户何时滚动到 LazyVGrid 的底部?的主要内容,如果未能解决你的问题,请参考以下文章
如何判断用户何时在 React-Native 中回答了 iOS 通知权限请求
如何检测滚动到水平 UICollectionView 的末尾