如何在 SwiftUI 中制作动态 PageViewController?

Posted

技术标签:

【中文标题】如何在 SwiftUI 中制作动态 PageViewController?【英文标题】:How to make a Dynamic PageViewController in SwiftUI? 【发布时间】:2020-09-23 17:10:56 【问题描述】:

有人知道如何在 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
    

【问题讨论】:

您找到解决方案了吗?我试图实现相同的功能 【参考方案1】:

您可以使用数组和ForEach 动态创建视图。

这是一个使用字符串数组的示例:

// See edited section

您可以在视图初始化程序中传递您想要的项目

编辑: 这是每次到达最后一个页面时添加新页面的示例:

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) 很重要,因为它会在数组更改时强制视图重新加载。

【讨论】:

这很酷,但这仍然是静态的。有没有办法使数据源动态化并使用 ForEach?这个想法是你向左滑动,过去一天,向右滑动,未来一天。 我设法在每次到达最后一个时动态添加一个View,但是当它添加时,由于渲染了整个View,所以没有动画,请检查编辑

以上是关于如何在 SwiftUI 中制作动态 PageViewController?的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 中的动态过滤器(谓词)

Swift UI - 如何制作图像网格?

如何在 SwiftUI 中制作水平列表?

如何在 SwiftUI 的 ScrollView 中制作动画? SwiftUI 中的手风琴风格动画

如何在 SwiftUI 中制作对角线轮播

如何在 SwiftUI 中制作斜体圆形样式系统文本?