[wwdc2023] ios17中的ScrollView的新增加
#教程 #ios #swift #swiftui

SwiftUI

随着iOS 17的引入,苹果添加了大量新的Scrollview修饰符,这些修饰符有望大大增强我们的应用程序开发体验。我认为测试它们并报告它们的工作原理是一个好主意。

我将在下面探索四个修饰符。

  1. .containerRelativeFrame(_:alignment:)
  2. .scrollTargetLayout(isEnabled:)
  3. .scrollTargetBehavior(_:)
  4. .scrollPosition(id:)

如果您喜欢这篇文章,请随时喜欢它或给我关注。
好的!让我们进入它!

1.冷0

这种新的修饰符允许我们指定视图的高度,宽度或相对于其容器视图的两者。在我们的示例中,我们在ZStack上使用了它。在这里,我们将其高度和宽度相对于容器视图,在这种情况下为ScrollView

struct ScrollExamplePaging: View {
    var body: some View {
        ScrollView(.horizontal) {
            let strings: [String] = ["1", "2", "3", "4", "5"]
            LazyHStack(spacing: 16) {
                ForEach(strings, id: \.self) { string in
                    ZStack {
                        // ...
                    }
                    .padding(16)
                    .containerRelativeFrame(.horizontal)
                    .containerRelativeFrame(.vertical)
                }
            }
        }
    }
}

这可以简化为以下内容:

.containerRelativeFrame([.vertical, .horizontal])

看起来像这样:

Example01

此修饰符不仅限于ScrollView。根据苹果的文档,可以在以下情况下使用:

  • 在iPados或macOS上呈现视图的窗口,或iOS上的设备屏幕。
  • navigationsplitview的一列
  • 导航框架
  • tabview的选项卡
  • 滚动视图,例如scrollview或list

2. .scrollTargetLayout(isEnabled:)

ScrollView中,滚动目标布局修饰符连接到主视图(容器视图),在这种情况下为ZStack。它可以让滚动浏览确定应对齐的位置。它设定了给定ScrollView的滚动目标。默认情况下设置为true。

struct ScrollExamplePaging: View {
    var body: some View {
        ScrollView(.horizontal) {
            let strings: [String] = ["1", "2", "3", "4", "5"]
            LazyHStack(spacing: 16) {
                ForEach(strings, id: \.self) { string in
                    ZStack {
                        // ...
                    }
                    .padding(16)
                    .containerRelativeFrame([.vertical, .horizontal])
                }
            }
            .scrollTargetLayout()
        }
    }
}

此修饰符本身不会对视图没有影响,我们必须将其与3.和4中的修饰符结合使用。

3. .scrollTargetBehavior(_:)

现在,让我们从在第2节中设置目标到定义我们的ScrollView的行为 - 本质上告诉我们的ScrollView如何运作。这涉及为我们的ScrollView选择.paging.viewAligned之类的行为。让我们深入研究这些。

.paging

.paging行为将您的ScrollView转换为分页的界面,想想Tiktok的垂直滚动或平滑的登机体验。此行为利用视图的高度和宽度从一个页面顺利过渡到另一页,确保始终显示完整的视图而不会切割它的任何部分。

实施。启动时,重要的是要确保LazyHStack的间距设置为0,因为此行为需要容器视图占据全屏宽度。

间距设置为16(分页行为被破坏)

Example04

间距设置为0(正常分页行为)

Example02

这是代码:

struct ScrollExamplePaging: View {
    var body: some View {
        ScrollView(.horizontal) {
            let strings: [String] = ["1", "2", "3", "4", "5"]
            LazyHStack(spacing: 16) {
                ForEach(strings, id: \.self) { string in
                    ZStack {
                        RoundedRectangle(cornerRadius: 16)
                            .fill(.black.gradient)

                        Text(string)
                            .font(.system(size: 92))
                            .fontWeight(.bold)
                            .foregroundStyle(.white)

                    }
                    .padding(16)
                    .containerRelativeFrame([.vertical, .horizontal])
                }
            }
            .scrollTargetLayout()
        }
        .scrollTargetBehavior(.paging)
    }
}

.viewAligned

对于要结合间距或创建更多复杂的布局时,.viewAligned行为派上用场。这允许自定义ScrollView的启动位置,以确保滚动时与容器视图平稳对齐。此功能为您的布局提供了增加的灵活性。

Example05

这是代码:

struct ScrollExamplePaging: View {
    var body: some View {
        ScrollView(.horizontal) {
            let strings: [String] = ["1", "2", "3", "4", "5"]
            HStack(spacing: 16) {
                ForEach(strings, id: \.self) { string in
                    ZStack {
                        RoundedRectangle(cornerRadius: 16)
                            .fill(.black.gradient)

                        Text(string)
                            .font(.system(size: 92))
                            .fontWeight(.bold)
                            .foregroundStyle(.white)

                    }
                    .frame(width: 300)
                    .containerRelativeFrame(.vertical)
                }
            }
            .scrollTargetLayout()
        }
        .scrollTargetBehavior(.viewAligned)
    }
}

4. Kound3

现在,我们可以使用滚动位置跟踪在滚动视图中显示的项目。使用非常简单。创建一个@State变量@State private var scrollPosition,然后将其绑定到修饰符。 .scrollPosition(id: $scrollPosition)。现在,当我滚动时,ScrollView将跟踪它显示的值。这意味着我们能够将此值与其他视图联系起来。

喜欢:

Example07

这是代码:

struct ScrollViewExampleScrollPosition: View {
    @State private var scrollPosition: String?
    let strings: [String] = ["1", "2", "3", "4", "5"]
    var body: some View {
        GeometryReader { geo in
            let size = geo.size
            VStack {
                ScrollView(.horizontal) {
                    HStack(spacing: 16) {
                        ForEach(strings, id: \.self) { string in
                            ZStack(alignment: .center) {
                                RoundedRectangle(cornerRadius: 16)
                                    .fill(.black.gradient)

                                Text(string)
                                    .font(.system(size: 92))
                                    .fontWeight(.bold)
                                    .foregroundStyle(.white)

                            }
                            .frame(width: 300, height: 500)
                            .padding(.vertical, 16)
                            .padding(.horizontal, (size.width - 300) / 2)
                        }
                    }
                    .scrollTargetLayout()
                }
                .scrollTargetBehavior(.viewAligned)
                .scrollPosition(id: $scrollPosition)

                VStack {
                    if let scrollPosition {
                        Text(scrollPosition)
                            .font(.largeTitle)
                    }
                }
            }
        }
    }
}

,或者我们可以使用按钮跳到我们想要看到的数字。

喜欢:

Example06

这是代码:

struct ScrollViewExampleScrollPosition: View {
    @State private var scrollPosition: String?
    let strings: [String] = ["1", "2", "3", "4", "5"]
    var body: some View {
        GeometryReader { geo in
            let size = geo.size
            VStack {
                ScrollView(.horizontal) {
                    HStack(spacing: 16) {
                        ForEach(strings, id: \.self) { string in
                            ZStack(alignment: .center) {
                                RoundedRectangle(cornerRadius: 16)
                                    .fill(.black.gradient)

                                Text(string)
                                    .font(.system(size: 92))
                                    .fontWeight(.bold)
                                    .foregroundStyle(.white)

                            }
                            .frame(width: 300, height: 500)
                            .padding(.vertical, 16)
                            .padding(.horizontal, (size.width - 300) / 2)
                        }
                    }
                    .scrollTargetLayout()
                }
                .scrollTargetBehavior(.viewAligned)
                .scrollPosition(id: $scrollPosition)

                VStack {
                    ForEach(strings, id: \.self) { string in
                        Button("Scroll to \(string)") {
                            withAnimation {
                                scrollPosition = string
                            }
                        }
                        .buttonStyle(.borderedProminent)
                    }
                }
            }
        }
    }
}

感谢您查看帖子。在第2部分中,我将查看Scrollview Transitions!关注以保持最新。
最好!

Dean Thompson

跟着我!
LinkedIn
Twitter
Instagram

参考