swiftui - 如何在 SwiftUI 中制作动态 PageViewController?
问题描述
有人知道如何在 SwiftUI、iOS 14 中制作动态 pageView 控制器吗?显示与日期相关的页面的东西,以便人们可以向左或向右滚动以查看过去、现在和未来的数据。
struct DatePg: View
{
let date: Date
var body: some View {
Text(date.description)
}
}
有一个新的 API 允许使用 TabView 和 viewModifier 创建一个 PageViewController。但我见过的唯一例子是静态的。这是一个静态 PageView 的示例。
import SwiftUI
struct SwiftUIPageView: View
{
@State private var selection = 0
var body: some View {
TabView(selection: $selection) {
Text("Hello")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.blue)
.tag(0)
Text("World")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.red)
.tag(1)
}.tabViewStyle(PageTabViewStyle())
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
}
}
已经有一些使用 UIHostingController 的东西,但是通过 UIKit 对象传递 NSManageObjectContext 正在引起问题。
这就是我目前所处的位置。还是行不通。
import SwiftUI
@main struct PagerApp: App
{
var body: some Scene {
WindowGroup { DatePageView() }
}
}
struct DatePageView: View
{
@StateObject var dateData = DateData(present: Date())
@State var index: Int = 1
var body: some View {
TabView(selection: $index) {
ForEach(dateData.dates, id: \.self) { date in
Text(date.description)
.onAppear { dateData.current(date: date) }
.tag(dateData.tag(date: date))
}
}
.tabViewStyle(PageTabViewStyle())
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
}
}
class DateData: ObservableObject
{
@Published var dates: [Date]
init(present: Date) {
let past = present.previousDay()
let future = present.nextDay()
self.dates = [past, present, future]
}
func current(date: Date) {
//center around
guard let i = dates.firstIndex(of: date) else { fatalError() }
self.dates = [ dates[i].previousDay(), dates[i], dates[i].nextDay() ]
print("make item at \(i) present")
}
func tag(date: Date) -> Int {
guard let i = dates.firstIndex(of: date) else { fatalError() }
return i
}
}
解决方案
您可以使用数组和动态创建视图ForEach
。
下面是一个使用字符串数组的示例:
// See edited section
您可以在 View 初始化程序中传递所需的项目
编辑:
这是每次到达最后一个页面时添加新页面的示例:
struct SwiftUIPageView: View
{
@State private var selection = "0"
@State var items: [String] = ["0", "1", "2", "3"]
var body: some View {
TabView(selection: $selection) {
ForEach(items, id: \.self) { item in
Text(item)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.red)
.tag(item)
}
}.tabViewStyle(PageTabViewStyle())
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
.onChange(of: selection, perform: { value in
if Int(value) == (self.items.count - 1) {
self.items.append("\(self.items.count)")
}
})
.id(items)
}
}
最后id(items)
一点很重要,因为它会在数组更改时强制视图重新加载。
推荐阅读
- javascript - 无法使用 selenium 或 javascript 在 Safari 浏览器中拖动滑块
- python - 在 Python 中绘制耦合常微分方程系统的向量场
- java - 签名密钥的算法“SHA256withECDSA”不等于有效的 HmacSHA* 算法名称,不能与 HS512 一起使用
- c# - 如何从 asp.net 核心中的 startup.cs 获取 HTTP 标头值?
- javascript - createAsyncThunk: 错误: addCase 不能用两个 reducer 调用相同的操作类型
- javascript - Reactjs,Typescript 错误 TS2322:类型 {} 不可分配给类型“IntrinsicAttributes & IntrinsicClassAttributes”
- javascript - React axios 编译失败
- javascript - JS - 将数组从一个文件导出到另一个文件
- c# - 在 swagger 模型模式中隐藏 DTO 字段,但在响应 json 中显示这些字段
- javascript - 如何将此请求发送到另一台主机?