-
onScrollGeometryChange(for:of:action:): Agrega una acción cuando un valor creado a partir de unScrollGeometrycambia.
Un ScrollGeometry tiene las siguientes propiedades:
-
bounds: ElCGRectdelScrollView. -
containerSize: Tamaño (CGSize) del contenedor delScrollView. -
contentInsets: Márgenes del contenido delScrollView. -
contentOffset: Offset (CGPoint) del contenido delScrollView. -
contentSize: Tamaño (CGSize) del contenido delScrollView. -
visibleRect: Rectángulo (CGRect) visible delScrollView
struct ContentView: View {
let data: [Content] = [
.init(text: "1"),
.init(text: "2"),
.init(text: "3"),
.init(text: "4"),
.init(text: "5"),
.init(text: "6"),
.init(text: "7"),
.init(text: "8"),
.init(text: "9"),
.init(text: "10"),
.init(text: "11"),
.init(text: "12"),
.init(text: "13"),
.init(text: "14"),
.init(text: "15"),
.init(text: "16"),
.init(text: "17"),
.init(text: "18"),
.init(text: "19"),
.init(text: "20"),
.init(text: "21"),
]
@State var selected: Content? = nil
@State var loaded = false
@State var pageNumber = 1
var body: some View {
VStack {
Spacer()
Text("Página actual: \(pageNumber)")
ScrollViewReader { proxy in
ScrollView(.horizontal) {
LazyHStack {
ForEach(data) { i in
Text("Item: [\(i.text)]")
.background(i.id == selected?.id ? .gray : .clear)
.containerRelativeFrame(.horizontal, count: 8, span: 1, spacing: 0, alignment: .center)
.scrollTransition(.interactive, axis: .horizontal) { effect, phase in
effect
.opacity(phase.isIdentity ? 1: 0)
.scaleEffect(phase.isIdentity ? 1 : 0.5)
}
.if(loaded && (i.id == data.last?.id || i.id == data.first?.id)) {
$0
.onScrollVisibilityChange(threshold: 0.5) { visible in
if visible {
print("Debo cargar más entradas")
}
}
}
}
}
.scrollTargetLayout()
}
.frame(height: 100)
// ⚠️ La alineación se hace por página
.scrollTargetBehavior(.paging)
.onScrollGeometryChange(for: Int.self, of: { geometry in
let totalWidth = geometry.containerSize.width
let currentPosition = geometry.contentOffset.x
let relativePosition = Int((currentPosition / totalWidth).rounded())
return relativePosition + 1
}, action: { oldValue, newValue in
pageNumber = newValue
})
.onAppear {
Task {
try! await Task.sleep(for: .milliseconds(50))
selected = data[data.count / 2]
// ⚠️ Como la alineación es por página, se deben alinear los bordes "leading" si quiero centrar una página
proxy.scrollTo(selected!.id, anchor: .leading)
try! await Task.sleep(for: .milliseconds(50))
loaded = true
}
}
}
Spacer()
}
}
}

Top comments (0)