首页 > 其他分享 >如何使用 SwiftUI 中 ScrollView 的滚动偏移

如何使用 SwiftUI 中 ScrollView 的滚动偏移

时间:2024-07-22 23:25:40浏览次数:16  
标签:index 滚动 ScrollPosition 视图 偏移 ScrollView position var SwiftUI

在这里插入图片描述

在这里插入图片描述

文章目录

前言

WWDC 24 已经结束,我决定开始写一些关于 SwiftUI 框架即将推出的新特性的文章。今年,苹果继续填补空白,引入了对滚动位置更细粒度的控制。本周,我们将学习如何操作和读取滚动偏移。

使用 scrollPosition

SwiftUI 框架已经允许我们通过视图标识符跟踪和设置滚动视图的位置。这种方法效果不错,但不足以更准确地跟踪用户交互。

struct ContentView: View {
    @State private var position: Int?
    
    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(0..<100) { index in
                    Text(verbatim: index.formatted())
                        .id(index)
                }
            }
            .scrollTargetLayout()
        }
        .scrollPosition(id: $position)
    }
}

在上面的代码示例中,我们使用了视图标识符和 scrollPosition 修饰符来跟踪和设置滚动视图的位置。虽然这种方法效果不错,但在某些情况下,尤其是需要更精确的用户交互跟踪时,它可能不够用。为了弥补这一不足,SwiftUI 引入了新的 ScrollPosition 类型,使我们能够通过偏移量、滚动视图的边缘、视图标识符等组合滚动位置。

新的 ScrollPosition 类型

SwiftUI 框架引入了新的 ScrollPosition 类型,使我们能够通过偏移量、滚动视图的边缘、视图标识符等组合滚动位置。

struct ContentView: View {
    @State private var position = ScrollPosition(edge: .top)
    
    var body: some View {
        ScrollView {
            Button("Scroll to bottom") {
                position.scrollTo(edge: .bottom)
            }
            
            ForEach(1..<100) { index in
                Text(verbatim: index.formatted())
                    .id(index)
            }
            
            Button("Scroll to top") {
                position.scrollTo(edge: .top)
            }
        }
        .scrollPosition($position)
    }
}

如上例所示,我们定义了 position 状态属性,并使用 scrollPosition 视图修饰符将滚动视图与状态属性绑定。我们还放置了两个按钮,允许你快速滚动到滚动视图中的第一个或最后一个项目。ScrollPosition 类型提供了许多重载的 scrollTo 函数,使我们能够处理不同的情况。

为滚动添加动画

通过附加动画视图修饰符并传递 ScrollPosition 类型的实例作为 value 参数,我们可以轻松地为编程滚动添加动画。

struct ContentView: View {
    @State private var position = ScrollPosition(edge: .top)
    
    var body: some View {
        ScrollView {
            Button("Scroll to bottom") {
                position.scrollTo(edge: .bottom)
            }
            
            ForEach(1..<100) { index in
                Text(verbatim: index.formatted())
                    .id(index)
            }
            
            Button("Scroll to top") {
                position.scrollTo(edge: .top)
            }
        }
        .scrollPosition($position)
        .animation(.default, value: position)
    }
}

滚动到特定项目

我们添加了另一个按钮来将滚动视图的位置更改为随机项目。我们仍然使用 ScrollPosition 类型的 scrollTo 函数,但我们提供了一个可哈希的标识符。这个选项允许我们将位置更改为特定项目,通过使用 anchor 参数,我们可以选择所选视图的哪个点应该可见。

struct ContentView: View {
    @State private var position = ScrollPosition(edge: .top)
    
    var body: some View {
        ScrollView {
            Button("Scroll somewhere") {
                let id = (1..<100).randomElement() ?? 0
                position.scrollTo(id: id, anchor: .center)
            }
            
            ForEach(1..<100) { index in
                Text(verbatim: index.formatted())
                    .id(index)
            }
        }
        .scrollPosition($position)
        .animation(.default, value: position)
    }
}

滚动到特定偏移

最后但同样重要的是 scrollTo 函数的 point 参数重载,允许我们传递 CGPoint 实例以将视图滚动到内容的特定点。

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)
    }
}

如上例所示,我们使用带有 CGPoint 参数的 scrollTo 函数。它还提供重载,允许我们仅按 X 或 Y 轴滚动视图。

struct ContentView: View {
    @State private var position = ScrollPosition(edge: .top)
    
    var body: some View {
        ScrollView {            
            Button("Scroll to offset") {
                position.scrollTo(y: 100)
                position.scrollTo(x: 200)
            }
            
            ForEach(1..<100) { index in
                Text(verbatim: index.formatted())
                    .id(index)
            }
        }
        .scrollPosition($position)
        .animation(.default, value: position)
    }
}

读取滚动位置

我们学习了如何使用新的 ScrollPosition 类型操作滚动位置,这也允许我们读取滚动视图的位置。ScrollPosition 提供了可选的 edge、point 和 viewID 属性,以在你编程滚动时读取值。

每当用户与滚动视图交互时,这些属性将变为 nil。ScrollPosition 类型上的 isPositionedByUser 属性允许我们了解何时用户手势移动滚动视图内容。

提供一个可以运行示例

下面是一个可以运行的示例代码,演示如何读取和显示滚动视图的位置。我们将使用一个 Text 视图来显示当前滚动位置:

import SwiftUI

struct ContentView: View {
    @State private var position = ScrollPosition(edge: .top)
    @State private var scrollOffset: CGPoint?

    var body: some View {
        VStack {
            ScrollView {
                LazyVStack {
                    ForEach(0..<100) { index in
                        Text("Item \(index)")
                            .id(index)
                            .padding()
                            .background(Color.yellow)
                            .cornerRadius(10)
                            .padding(.horizontal)
                    }
                }
                .scrollPosition($position)
                .onScrollGeometryChange { geometry in
                    scrollOffset = geometry?.contentBounds.origin
                }
            }
            .animation(.default, value: position)
            
            if let offset = scrollOffset {
                Text("Scroll Offset: x = \(Int(offset.x)), y = \(Int(offset.y))")
                    .padding()
            } else {
                Text("Scroll Offset: not available")
                    .padding()
            }
        }
        .padding()
    }
}

在这个示例中,我们使用了 onScrollGeometryChange 修饰符来读取滚动视图的几何变化。每当滚动视图滚动时,geometry?.contentBounds.origin 将提供当前滚动位置的偏移量。我们将这个偏移量存储在 scrollOffset 状态属性中,并在视图底部显示当前的滚动位置。

总结

在本文中,我们深入探讨了 SwiftUI 框架中 ScrollView 的新特性,特别是如何通过 ScrollPosition 类型实现更精确的滚动控制。我们介绍了如何使用 ScrollPosition 类型进行滚动位置的设置和读取,包括使用偏移量、视图标识符等方式进行操作。此外,我们还展示了如何通过动画和事件处理来增强用户体验。通过这些新功能,开发者可以更灵活地控制滚动视图的行为,从而创建更加流畅和直观的用户界面。希望这些内容对你有所帮助。

标签:index,滚动,ScrollPosition,视图,偏移,ScrollView,position,var,SwiftUI
From: https://blog.csdn.net/qq_36478920/article/details/140621946

相关文章

  • Unity UGUI 之 ScrollBar与ScrollView
    本文仅作学习笔记与交流,不作任何商业用途本文包括但不限于unity官方手册,唐老狮,麦扣教程知识,引用会标记,如有不足还请斧正1.什么是ScrollBar滚动块:Unity-Manual:Scrollbar2.重要参数该笔记来源唐老狮:重复参数不过多赘述请看该博客:UnityUGUI之Button-CSDN博客F.......
  • SwiftUI中全局EnvironmentObject的使用和注意事项,实现多界面共享数据
    SwiftUI的@EnvironmentObject是一个强大的工具,它允许你在多个视图之间共享数据(使用一个可观察对象)。当你有一个复杂的视图层次结构,并且需要在没有直接连接的视图之间共享相同的可观察对象时,它特别有用。创建ObservableObject协议类要使用环境对象,首先需要创建一个符合Obse......
  • swiftui中使用scaleEffect和rotationEffect实现缩放和旋转效果
    在SwiftUI中,你可以使用.scaleEffect()和.rotationEffect()来实现缩放和旋转动画,缩放和旋转的内容可以是图片,文字等view视图。scaleEffect可以实现缩放效果,配合动画可以实现好看的过度效果,其中的参数是缩放的倍数,1表示原本大小,大于1表示放大,小于1表示缩小。示例代码:Text("He......
  • SwiftUI Release 引入的辅助焦点管理
    文章目录前言使用@FocusState属性包装器高级技巧:专用辅助技术可聚焦字段的高级用法优化体验运行截图总结前言SwiftUIRelease引入了强大的新功能,其中之一是辅助焦点管理。这个新功能使得在SwiftUI中处理辅助技术(如VoiceOver和SwitchControl)的焦点状态变得......
  • 如何在 SwiftUI 中熟练使用 visualEffect 修饰符
    文章目录前言介绍visualEffect什么是视觉效果?visualEffect修饰符视觉效果完整的代码总结前言在WWDC23中,SwiftUI引入了一个名为visualEffect的新视图修饰符。此修饰符允许我们通过访问特定视图的布局信息来附加一组可动画化的视觉效果。下面我们将学习如何......
  • 在 SwiftUI 中的作用域动画
    文章目录前言简单示例动画视图修饰符使用多个可动画属性使用ViewBuilder总结前言从一开始,动画就是SwiftUI最强大的功能之一。你可以在SwiftUI中快速构建流畅的动画。唯一的缺点是每当我们需要运行多步动画或将动画范围限定到视图层次结构的特定部分时,我们如......
  • swiftUI
    SwiftUI是苹果推出的一种现代化方式,用于创建跨所有Apple平台的用户界面。它通过声明性语法简化了UI的开发流程。下面是一个基本的SwiftUI示例,展示了如何使用SwiftUI构建一个简单的"HelloWorld"应用。示例步骤1.创建一个新的SwiftUI项目打开Xcode,选择"新建项目......
  • swiftui中TabView使用,以及Tab使用注意
    TabView官方文档:TabView|AppleDeveloperDocumentationTab官网文档:Tab|AppleDeveloperDocumentation使用交互式用户界面元素在多个子视图之间切换的视图。也就是手机底部的几个导航菜单一样,但是注意官方给的例子里面有使用Tab组件的,但是这个Tab组件注意:暂时只支持bet......
  • Kafka 新的消费组默认的偏移量设置和消费行为
    个人名片......
  • 【C语言】宏offsetof的模拟实现(计算结构体中某变量相对于首地址的偏移)
    首先我们应该特别留意:offsetof是一个宏,并非是一个函数!宏offsetof的介绍:参数:第一个是结构体类型名称,第二个是结构体成员名返回类型:size_t无符号整形引用的头文件:<stddef.h>offsetof的使用举列:#include<stddef.h>structStu//注释为相对于起始位置的偏移量{......