赞
踩
本文探讨了如何使用 onScrollGeometryChange
视图修饰符有效地监控和管理滚动位置和几何。通过详细的代码示例和解释,你将学习如何利用这些工具创建动态和响应迅速的用户界面。
SwiftUI 是一个强大的框架,它简化了在苹果平台上构建用户界面的过程。SwiftUI 中的一个基本组件是 ScrollView,它允许用户通过滚动导航内容。然而,管理滚动位置和理解滚动交互可能是一个挑战。ScrollGeometry 和 onScrollGeometryChange 视图修饰符的引入解决了这些挑战,为开发者提供了更多的控制和对滚动行为的深入了解。
ScrollPosition 是一种类型,允许开发者以编程方式读取或更改滚动位置。虽然有用,但当用户使用手势与滚动视图交互时,它显得不够全面。以下是一个展示 ScrollPosition 使用的示例:
struct ContentView: View { @State private var position = ScrollPosition(edge: .top) var body: some View { ScrollView { Button("Scroll to offset") { position.scrollTo(point: CGPoint(x: 0, y: 100)) } ForEach(1..<100) { index in Text(verbatim: index.formatted()) .id(index) } } .scrollPosition($position) .animation(.default, value: position) } }
在这个示例中,我们将滚动视图绑定到一个状态属性。当按下按钮时,滚动视图会将其内容偏移移动到指定点。然而,我们无法读取用户通过手势交互设置的具体内容偏移。
SwiftUI 的新 ScrollGeometry 类型以及 onScrollGeometryChange 视图修饰符提供了一个解决方案。这些工具允许开发者在用户交互期间准确读取内容偏移。
让我们探索如何使用 onScrollGeometryChange 视图修饰符与 ScrollGeometry:
struct ContentView: View { @State private var scrollPosition = ScrollPosition(y: 0) @State private var offsetY: CGFloat = 0 var body: some View { ScrollView { ForEach(1..<100, id: \.self) { number in Text(verbatim: number.formatted()) .id(number) } } .scrollPosition($scrollPosition) .onScrollGeometryChange(for: CGFloat.self) { geometry in geometry.contentOffset.y } action: { oldValue, newValue in if oldValue != newValue { offsetY = newValue } } .onChange(of: offsetY) { print(offsetY) } } }
onScrollGeometryChange 视图修饰符接受三个参数:
CGFloat
来跟踪内容偏移的 Y 轴。ScrollGeometry 提供了许多有价值的属性,如内容偏移、边界、容器大小、可见矩形、内容插入和内容大小。开发者可以提取单个属性或组合多个属性以获得全面的见解。
以下是一个结合内容大小和可见矩形跟踪的示例:
struct ContentView: View { struct ScrollData: Equatable { let size: CGSize let visible: CGRect } @State private var scrollPosition = ScrollPosition(y: 0) @State private var scrollData = ScrollData(size: .zero, visible: .zero) var body: some View { ScrollView { ForEach(1..<100, id: \.self) { number in Text(verbatim: number.formatted()) .id(number) } } .scrollPosition($scrollPosition) .onScrollGeometryChange(for: ScrollData.self) { geometry in ScrollData(size: geometry.contentSize, visible: geometry.visibleRect) } action: { oldValue, newValue in if oldValue != newValue { scrollData = newValue } } .onChange(of: scrollData) { print(scrollData) } } }
在这个示例中,我们定义了一个 ScrollData
结构来保存大小和可见矩形属性。在使用 onScrollGeometryChange 视图修饰符时,我们将 ScrollData
作为转换闭包的返回类型,从 ScrollGeometry 实例中提取所有所需的数据。
下面是一个完整的 SwiftUI Demo,其中包含了我们刚刚讨论的 ScrollView、ScrollGeometry 和 onScrollGeometryChange 的使用示例。你可以在 Xcode 中运行这个项目来观察其效果。
完整代码示例
import SwiftUI struct ContentView: View { @State private var scrollPosition = ScrollPosition(y: 0) @State private var offsetY: CGFloat = 0 var body: some View { VStack { Text("Scroll Offset: \(offsetY, specifier: "%.2f")") .padding() ScrollView { ForEach(1..<100, id: \.self) { number in Text(verbatim: number.formatted()) .padding() .frame(maxWidth: .infinity) .background(Color(.secondarySystemBackground)) .cornerRadius(8) .padding(.horizontal) .id(number) } } .scrollPosition($scrollPosition) .onScrollGeometryChange(for: CGFloat.self) { geometry in geometry.contentOffset.y } action: { oldValue, newValue in if oldValue != newValue { offsetY = newValue } } .onChange(of: offsetY) { print(offsetY) } } } } struct ScrollData: Equatable { let size: CGSize let visible: CGRect } struct AdvancedContentView: View { @State private var scrollPosition = ScrollPosition(y: 0) @State private var scrollData = ScrollData(size: .zero, visible: .zero) var body: some View { VStack { Text("Content Size: \(scrollData.size.width, specifier: "%.2f") x \(scrollData.size.height, specifier: "%.2f")") .padding() Text("Visible Rect: \(scrollData.visible.origin.x, specifier: "%.2f"), \(scrollData.visible.origin.y, specifier: "%.2f") - \(scrollData.visible.width, specifier: "%.2f") x \(scrollData.visible.height, specifier: "%.2f")") .padding() ScrollView { ForEach(1..<100, id: \.self) { number in Text(verbatim: number.formatted()) .padding() .frame(maxWidth: .infinity) .background(Color(.secondarySystemBackground)) .cornerRadius(8) .padding(.horizontal) .id(number) } } .scrollPosition($scrollPosition) .onScrollGeometryChange(for: ScrollData.self) { geometry in ScrollData(size: geometry.contentSize, visible: geometry.visibleRect) } action: { oldValue, newValue in if oldValue != newValue { scrollData = newValue } } .onChange(of: scrollData) { print(scrollData) } } } } @main struct ScrollViewDemoApp: App { var body: some Scene { WindowGroup { TabView { ContentView() .tabItem { Label("Basic", systemImage: "1.square.fill") } AdvancedContentView() .tabItem { Label("Advanced", systemImage: "2.square.fill") } } } } }
如何运行
ContentView.swift
文件替换为上面的完整代码。@main
注释下的应用程序入口点中,确保你的主视图是 ScrollViewDemoApp
。功能解释
ContentView
: 展示基本的滚动偏移追踪功能,通过 onScrollGeometryChange
视图修饰符追踪 Y 轴的内容偏移。AdvancedContentView
: 展示更高级的滚动几何追踪功能,追踪内容大小和可见矩形的变化。ScrollViewDemoApp
: 包含 TabView
,方便在基本和高级示例之间切换。今天,我们探讨了 SwiftUI 中的新 ScrollGeometry 类型和 onScrollGeometryChange 视图修饰符。这些工具为开发者提供了对滚动位置和交互的精确控制和洞察,增强了动态和响应迅速的用户界面的开发。通过利用这些功能,你可以创建更具吸引力和直观的应用程序。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。