ElegantPages 是一个使用 SwiftUI 编写的高效且可定制的全屏页面视图。
ElegantPages 包含两种类型的组件,ElegantPagesView 和 ElegantListView。
为了更简单的使用,推荐使用 ElegantPagesView,因为它会立即加载所有页面视图。
为了更复杂的使用,推荐使用 ElegantListView,因为它会按需加载页面视图(了解更多)。
这两个视图的优点在于它们的工作方式与分页组件应有的方式一致。 在 SwiftUI 中经常出现的一个错误是,ScrollView、List 或任何 Gesture 几乎肯定会干扰视图中的其他手势。 然而,ElegantPages 修复了这个问题,即使嵌入了 Gestures,滚动分页组件也非常流畅。
ElegantPagesView 组件可以通过 ElegantHPages 和 ElegantVPages 来使用。
import ElegantPages
struct ElegantVPagesExample: View {
let manager = ElegantPagesManager(startingPage: 1, pageTurnType: .earlyCutOffDefault)
var body: some View {
ElegantVPages(manager: manager) {
CustomButtonView()
CustomView()
CustomListView()
}
}
}
ElegantListView 组件可以通过 ElegantHList 和 ElegantVList 来使用。
import ElegantPages
let listData = (1...40).map { _ in "Ideally, this should be more dynamic content to make the most use out of this list" }
struct ElegantVListExample: View {
let manager = ElegantListManager(pageCount: vListData.count, pageTurnType: .earlyCutOffDefault)
var body: some View {
ElegantVList(manager: manager,
pageTurnType: .earlyCutOffDefault) { page in
ExampleView(page: page).erased
}
}
}
struct ExampleView: View {
let page: Int
var body: some View {
VStack {
Text("Page \(page)")
.font(.largeTitle)
Text(listData[page])
.font(.title)
}
.padding()
}
}
ElegantPagesView 非常简单。 它使用 函数构建器 来收集页面视图,并将它们放入 HStack 或 VStack 中,具体取决于所选的 ElegantPages 视图类型。 因此,所有视图都会立即创建。
ElegantListView 非常有趣。 为了获得更大的灵活性,它使用 @ViewBuilder 来获取任何给定页面的视图 (它是 ElegantVList 声明末尾的闭包)。 首次初始化时,它最多调用此闭包 3 次,以获取起始页面的视图。 这些视图用于初始化最多包含 3 个 UIHostingControllers 的数组,它们的 rootViews 设置为 UIViewController 中的特定原点。 关键在于,在任何给定时刻,最多只有 3 个页面被加载。 当用户滚动到下一页时,旧页面将被删除,新页面将被插入;视图本身会随着它们的起始位置随着翻页而改变而被调整。 这可以降低整体内存使用率,并使滚动速度极快。 如果您有兴趣,可以 偷看一下。
任何 ElegantPages 组件的以下方面都可以自定义
public enum PageTurnType {
case regular(pageTurnDelta: CGFloat)
case earlyCutoff(config: EarlyCutOffConfiguration)
}
public struct EarlyCutOffConfiguration {
public let scrollResistanceCutOff: CGFloat
public let pageTurnCutOff: CGFloat
public let pageTurnAnimation: Animation
}
常规翻页仅在用户结束拖动后翻页。
pageTurnDelta 表示用户必须在屏幕上拖动多远才能在松开时翻页的百分比。 此默认值为 0.3,作为 PageTurnType 扩展的一部分。PageTurnType.regularDefault 访问默认的常规翻页当用户在屏幕上拖动一定距离时,提前截止翻页会翻页。
scrollResistanceCutOff:视图在用户拖动时偏移的距离。pageTurnCutOff:用户在翻页之前必须在屏幕上拖动的距离 (一旦达到此值,页面将自动翻转到并且用户的正在进行的手势失效)。pageTurnAnimation:翻页时使用的动画PageTurnType.earlyCutOffDefault 访问默认的提前截止翻页如果 scrollResistanceCutOff 不清楚,这里有一个例子。 假设我们有一个可以水平拖动的视图。 如果您向右拖动 80 像素,那么您可见的偏移量也是 80 像素。 您滚动的量等于可见偏移量。 但是,如果您有一个 40 像素的滚动阻力,在向右拖动 80 像素后,您只会看到该视图向右移动了 40 像素。 这就是它被称为阻力的原因。
###$ viewForPage:每次显示新页面时调用的数据源方法,用于请求新页面的视图。 仅适用于 ElegantList 组件
// Use as a function
ElegantVList(..., viewForPage: exampleView)
func exampleView(for page: Int) -> AnyView { ExampleView(...) }
// Use as a closure
ElegantHList(...) { page in ExampleView(...) }
ElegantVList(...)
.onPageChanged(...)
ElegantHList(...)
.onPageChanged(...)
ElegantHPages(...)
.onPageChanged(...)
ElegantVPages(...)
.onPageChanged(...)
// You may want a smaller width for the VList. However, height for the VList will always be the screen height
ElegantVList(...)
.frame(width: ...)
// You may want a smaller height for the HList. However, width for the HList will always be the screen width
ElegantHList(...)
.frame(height: ...)
GIF 中显示的演示可以在 ElegantCalendar 上查看。
对于更简单的演示,请查看 示例仓库。
可以使用 Swift Package Manager 获取 ElegantPages
使用 Xcode 11,转到 File -> Swift Packages -> Add Package Dependency 并输入 https://github.com/ThasianX/ElegantPages
如果您正在使用 Package.swift,您也可以轻松地将 ElegantPages 添加为依赖项。
let package = Package(
name: "TestProject",
dependencies: [
.package(url: "https://github.com/ThasianX/ElegantPages", from: "1.4.0")
],
targets: [
.target(name: "TestProject", dependencies: ["ElegantPages"])
]
)
如果您发现错误,或者想建议一项新功能或改进,如果您能先搜索问题跟踪器,那将非常棒。虽然我们不介意重复,但保持问题的唯一性有助于我们节省时间并整合精力。 如果您找不到您的问题,请随时提交新问题。
本项目根据 MIT 许可证获得许可 - 有关详细信息,请参阅 LICENSE 文件