ScrollViewSectionKit 1.4.0

ScrollViewSectionKit 1.4.0

Pavol Kmeť 维护。



ScrollViewSectionKit

一个 SwiftUI 库,允许您在 ScrollView SwiftUI 组件中添加原生(plaingroupedinsetGrouped)或自定义的分节样式。

The preview of the `ScrollViewSectionKit` on iPhones 14 Pro Max. The 1st one shows plain style. The 2nd one shows grouped style. The 3rd one shows inset grouped style. The 4th one shows custom style.

概览

  • 💎 100% 使用 SwiftUI 制作。
  • 🚀 轻量级,无外部依赖。
  • ✅ API 力求模仿 Apple 的 List 组件,同时您也可以在其中使用 ScrollView 组件。
  • 🎨 预定义的 .plain.grouped.insetGrouped 分节样式,但您也可以完全自定义分节样式。
  • 🧪 在多个生产应用程序中进行测试。
  • 📑 详细的 API 文档。

要求

  • iOS 14.0+
  • watchOS 7.0+
  • tvOS 14.0+
  • macOS 11.0+

安装

Swift Package Manager

ScrollViewSectionKit 通过 Swift Package Manager 可用。

https://github.com/pavolkmet/ScrollViewSectionKit

CocoaPods

ScrollViewSectionKit 通过 CocoaPods 可用。要安装它,只需将以下行添加到 Podfile 中

pod 'ScrollViewSectionKit'

然后只需运行 pod install

手动安装

ScrollViewSectionKit 中的 Source 文件夹中的所有文件拖放到您的项目中,并选择 如有需要则复制项目

使用

import ScrollViewSectionKit

struct ContentView: View {
    
    var body: some View {
        ScrollView {
            VStack(spacing: 0.0) {
                ScrollViewSection {
                    Text("This is a 1st row.")
                    Text("This is a 2nd row.")
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
            }
        }
        .scrollViewSectionStyle(.insetGrouped)
        .scrollViewSectionBackgroundColor(.clear)
        .background {
            Color(uiColor: UIColor.systemGroupedBackground)
                .ignoresSafeArea()
        }
    }
    
}

查看 示例应用程序 以获取所有示例和高级用法。

配置

分节 - 样式

您可以通过使用 scrollViewSectionStyle(_ style: any ScrollViewSectionStyle) 修改器来自定义分节的显示。此修改器可用于全局或针对每个分节。库已经包含 .plain.grouped.insetGrouped 样式。

在以下示例中,第一个 ScrollViewSection 使用了 .grouped 样式,因为它被设置为 ScrollView 组件的一部分,但第二个 ScrollViewSection 使用了 .insetGrouped 样式。这是因为内部使用了 scrollViewSectionStyle(_ style: any ScrollViewSectionStyle) 修改器,它使用了 EnvironmentKey。这意味着您可以使用此修改器为整个应用程序设置全局样式。

import ScrollViewSectionKit

struct ContentView: View {
    
    var body: some View {
        ScrollView {
            VStack(spacing: 0.0) {
                ScrollViewSection {
                    Text("This is a 1st row.")
                    Text("This is a 2nd row.")
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                ScrollViewSection {
                    Text("This is a 1st row.")
                    Text("This is a 2nd row.")
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                .scrollViewSectionStyle(.insetGrouped)
            }
        }
        .scrollViewSectionStyle(.grouped)
        .scrollViewSectionBackgroundColor(.clear)
        .background {
            Color(uiColor: UIColor.systemGroupedBackground)
                .ignoresSafeArea()
        }
    }
    
}

它应该看起来像这样 ⬇️

分节 - 背景颜色

您可以通过使用 scrollViewSectionBackgroundColor(_ color: Color) 修改器来使用不同的背景颜色自定义分节的表现。此修改器可用于全局或针对每个分节。

以下示例中,第一个ScrollViewSection使用.blue.opacity(0.28)背景色,因为这个颜色被设置为ScrollView组件的一部分。然而,第二个ScrollViewSection使用.orange.opacity(0.28)背景色。这是因为底层中,scrollViewSectionBackgroundColor(_ color: Color)修改器正在使用EnvironmentKey。这意味着你可以使用这个修改器为整个应用程序设置全局样式。

import ScrollViewSectionKit

struct ContentView: View {
    
    var body: some View {
        ScrollView {
            VStack(spacing: 0.0) {
                ScrollViewSection {
                    Text("This is a 1st row.")
                    Text("This is a 2nd row.")
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                ScrollViewSection {
                    Text("This is a 1st row.")
                    Text("This is a 2nd row.")
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                .scrollViewSectionStyle(.insetGrouped)
                .scrollViewSectionBackgroundColor(.orange.opacity(0.28))
            }
        }
        .scrollViewSectionStyle(.grouped)
        .scrollViewSectionBackgroundColor(.blue.opacity(0.28))
        .background {
            Color(uiColor: UIColor.systemGroupedBackground)
                .ignoresSafeArea()
        }
    }
    
}

它应该看起来像这样 ⬇️

行 - 背景颜色

你可以通过应用不同的背景色来使用scrollViewRowBackgroundColor(_ color: Color?)修改器来自定义行的外观。这个修改器可以在每个部分或每行使用。

在以下示例中,第一个部分的第二行使用.blue.opacity(0.28)背景色,因为这已经是行的一部分设置的。另一方面,第二个部分的第一个行使用.green.opacity(0.28)背景色,因为整个部分使用了此修改器,第二个部分的最后一行则使用.orange.opacity(0.28)背景色。

import ScrollViewSectionKit

struct ContentView: View {
    
    var body: some View {
        ScrollView {
            VStack(spacing: 0.0) {
                ScrollViewSection {
                    Text("This is a 1st row.")
                    Text("This is a 2nd row.")
                        .scrollViewRowBackgroundColor(.blue.opacity(0.28))
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                ScrollViewSection {
                    Text("This is a 1st row.")
                    Text("This is a 2nd row.")
                        .scrollViewRowBackgroundColor(.orange.opacity(0.28))
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                .scrollViewSectionStyle(.insetGrouped)
                .scrollViewRowBackgroundColor(.green.opacity(0.28))
            }
        }
        .scrollViewSectionStyle(.grouped)
        .scrollViewSectionBackgroundColor(.clear)
        .background {
            Color(uiColor: UIColor.systemGroupedBackground)
                .ignoresSafeArea()
        }
    }
    
}

它应该看起来像这样 ⬇️

行 - 边距

你还可以通过应用不同的行内边距来使用scrollViewRowInsets(_ insets: EdgeInsets?)修改器来自定义行的外观。这个修改器可以在每个部分或每行使用。

在以下示例中,整个第一个部分使用EdgeInsets(top: 0.0, leading: 40.0, bottom: 0.0, trailing: 0.0)行内边距,因为整个部分使用了此修改器。另一方面,第二个部分的第一个行使用EdgeInsets(top: 0.0, leading: 40.0, bottom: 0.0, trailing: 0.0)行内边距,因为这只有一个行使用了此修改器,最后一行则使用默认的行内边距。

import ScrollViewSectionKit

struct ContentView: View {
    
    var body: some View {
        ScrollView {
            VStack(spacing: 0.0) {
                ScrollViewSection {
                    Text("This is a 1st row.")
                    Text("This is a 2nd row.")
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                .scrollViewRowInsets(EdgeInsets(top: 0.0, leading: 40.0, bottom: 0.0, trailing: 0.0))
                ScrollViewSection {
                    HStack(spacing: 10.0) {
                        Image(systemName: "person.fill")
                            .resizable()
                            .scaledToFit()
                            .frame(width: 20.0, height: 20.0)
                        Text("This is a 1st row.")
                    }
                    .scrollViewRowInsets(EdgeInsets(top: 0.0, leading: 40.0, bottom: 0.0, trailing: 0.0))
                    Text("This is a 2nd row.")
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                .scrollViewSectionStyle(.insetGrouped)
            }
        }
        .scrollViewSectionStyle(.grouped)
        .scrollViewSectionBackgroundColor(.clear)
        .background {
            Color(uiColor: UIColor.systemGroupedBackground)
                .ignoresSafeArea()
        }
    }
    
}

它应该看起来像这样 ⬇️

行 - 分隔线边距

在之前的示例中,我们调整了行内边距,但分隔符仍然使用默认的内边距。我们可以通过使用scrollViewRowSeparatorInsets(_ insets: EdgeInsets?)修改器来改变这一点。此修改器可以在每个部分或每行使用。

在以下示例中,整个第一个部分使用EdgeInsets(top: 0.0, leading: 40.0, bottom: 0.0, trailing: 0.0)行分隔内边距,因为整个部分使用了此修改器。另一方面,第二个部分的第一个行使用EdgeInsets(top: 0.0, leading: 70.0, bottom: 0.0, trailing: 0.0)行分隔内边距,因为这只有一个行使用了此修改器,最后一行使用默认的行分隔内边距。

import ScrollViewSectionKit

struct ContentView: View {
    
    var body: some View {
        ScrollView {
            VStack(spacing: 0.0) {
                ScrollViewSection {
                    Text("This is a 1st row.")
                    Text("This is a 2nd row.")
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                .scrollViewRowInsets(EdgeInsets(top: 0.0, leading: 40.0, bottom: 0.0, trailing: 0.0))
                .scrollViewRowSeparatorInsets(EdgeInsets(top: 0.0, leading: 40.0, bottom: 0.0, trailing: 0.0))
                ScrollViewSection {
                    HStack(spacing: 10.0) {
                        Image(systemName: "person.fill")
                            .resizable()
                            .scaledToFit()
                            .frame(width: 20.0, height: 20.0)
                        Text("This is a 1st row.")
                    }
                    .scrollViewRowInsets(EdgeInsets(top: 0.0, leading: 40.0, bottom: 0.0, trailing: 0.0))
                    .scrollViewRowSeparatorInsets(EdgeInsets(top: 0.0, leading: 70.0, bottom: 0.0, trailing: 0.0))
                    Text("This is a 2nd row.")
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                .scrollViewSectionStyle(.insetGrouped)
            }
        }
        .scrollViewSectionStyle(.grouped)
        .scrollViewSectionBackgroundColor(.clear)
        .background {
            Color(uiColor: UIColor.systemGroupedBackground)
                .ignoresSafeArea()
        }
    }
    
}

它应该看起来像这样 ⬇️

行 - 分隔线色调

你可以通过应用不同的调色板颜色来使用scrollViewRowSeparatorTint(_ color: Color?)修改器来自定义行的分隔外观。此修改器可以在每个部分或每行使用。

在以下示例中,第一个部分的第二行的分隔使用.blue调色板颜色,因为这已经是行的一部分设置的。另一方面,第二个部分的第一个和第三行的分隔使用.green调色板颜色,因为整个部分使用了此修改器,同一部分的第二行分隔则使用.orange调色板颜色。

import ScrollViewSectionKit

struct ContentView: View {
    
    var body: some View {
        ScrollView {
            VStack(spacing: 0.0) {
                ScrollViewSection {
                    Text("This is a 1st row.")
                    Text("This is a 2nd row.")
                        .scrollViewRowSeparatorTint(.blue)
                    Text("This is a 3nd row.")
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                ScrollViewSection {
                    Text("This is a 1st row.")
                    Text("This is a 2nd row.")
                        .scrollViewRowSeparatorTint(.orange)
                    Text("This is a 3nd row.")
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                .scrollViewSectionStyle(.insetGrouped)
                .scrollViewRowSeparatorTint(.green)
            }
        }
        .scrollViewSectionStyle(.grouped)
        .scrollViewSectionBackgroundColor(.clear)
        .background {
            Color(uiColor: UIColor.systemGroupedBackground)
                .ignoresSafeArea()
        }
    }
    
}

它应该看起来像这样 ⬇️

行 - 右键菜单

你还可以通过使用scrollViewRowContextMenu(@ViewBuilder _ menuItems: @escaping () -> some View)修改器为行添加上下文菜单。此修改器可以在每个部分或每行使用。

在以下示例中,第一个部分的第二行使用多个按钮,它们之间由Divider组件分隔。

import ScrollViewSectionKit

struct ContentView: View {
    
    var body: some View {
        ScrollView {
            VStack(spacing: 0.0) {
                ScrollViewSection {
                    Text("This is a 1st row.")
                    Text("This is a 2nd row.")
                        .scrollViewRowContextMenu {
                            Button {
                                
                            } label: {
                                Label("Star", systemImage: "star")
                            }
                            Button {
                                
                            } label: {
                                Label("Profile", systemImage: "person")
                            }
                            Divider()
                            Button(role: .destructive) {
                                
                            } label: {
                                Label("Block", systemImage: "hand.raised")
                            }
                        }
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                ScrollViewSection {
                    Text("This is a 1st row.")
                    Text("This is a 2nd row.")
                } header: {
                    Text("Section header".uppercased())
                } footer: {
                    Text("Section footer")
                }
                .scrollViewSectionStyle(.insetGrouped)
            }
        }
        .scrollViewSectionStyle(.grouped)
        .scrollViewSectionBackgroundColor(.clear)
        .background {
            Color(uiColor: UIColor.systemGroupedBackground)
                .ignoresSafeArea()
        }
    }
    
}

它应该看起来像这样 ⬇️

鸣谢

作者

许可证

MIT License

Copyright (c) 2023 Pavol Kmet

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.