我有以下用于在 LazyHStack 中显示图像的代码:
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(alignment: .top) {
let photos: [PhotoObject] = []//some array of photo objects
ForEach(photos, id: \.self) { item in
KFImage.url(URL(string: item.url))
.resizable()
.frame(width: 200, height: 200)
.cornerRadius(13)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想每次当堆栈中的第一个可见项目发生变化时执行一个函数(例如,当用户向左滚动太多时,最左边的图像不再可见,而右边的图像现在是第一个可见图像)。Android 的 Jetpack compose对此有非常简单的解决方案。我玩过自定义TrackableScrollView但这只返回偏移量,我不确定它是什么,因为它以 例如 开头1500
,当您滚动到末尾时,值是 ~ -1200
- 不知道应该如何根据偏移量计算索引一半是积极的,一半是消极的。
虽然 UIView 中有相同类型的内置函数,正如您所展示的,但这还没有内置到 SwiftUI 中,但您可以自己做。本质上,您所做的就是获取外部视图的坐标,在本例中是您的ScrollView
,并查看图像视图的内部坐标是否至少部分位于外部视图内。这是通过两个GeometryReaders
和一个.coordinateSpaces()
指示符完成的,因此我们可以可靠地位于同一坐标空间中。如果图像存在于外部坐标空间内,则将其添加到@State
作为集合的变量中。如果不是,则将其从集合中删除。这将为您提供当前部分或完全可见的视图的运行列表。
由于您没有提供最小的、可重现的示例,因此我采用了您的代码并用于Rectangles
表示您的图像,但您应该能够简单地重新插入您的代码。下面是一个工作示例:
struct ImageIsInView: View {
@State var visibleIndex: Set<Int> = [0,1]
var body: some View {
VStack {
Text(visibleIndex.map( { $0.description }).sorted().joined(separator: ", "))
// The outer GeometryReader has to go directly around your ScrollView
GeometryReader { outerProxy in
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(alignment: .top) {
ForEach(0..<10, id: \.self) { item in
GeometryReader { geometry in
Rectangle()
.fill(Color.orange)
.cornerRadius(13)
.overlay(
Text("Item: \(item)")
)
// every time the ScrollView moves, the inner geometry changes and is
// picked up here:
.onChange(of: geometry.frame(in: .named("scrollView"))) { imageRect in
if isInView(innerRect: imageRect, isIn: outerProxy) {
visibleIndex.insert(item)
} else {
visibleIndex.remove(item)
}
}
}
.frame(width: 200, height: 200)
}
}
}
.coordinateSpace(name: "scrollView")
}
}
}
private func isInView(innerRect:CGRect, isIn outerProxy:GeometryProxy) -> Bool {
let innerOrigin = innerRect.origin.x
let imageWidth = innerRect.width
let scrollOrigin = outerProxy.frame(in: .global).origin.x
let scrollWidth = outerProxy.size.width
if innerOrigin + imageWidth < scrollOrigin + scrollWidth && innerOrigin + imageWidth > scrollOrigin ||
innerOrigin + imageWidth > scrollOrigin && innerOrigin < scrollOrigin + scrollWidth {
return true
}
return false
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1760 次 |
最近记录: |