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 文件