我正在尝试创建一个双向的TabView(使用.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
),它的数据源会随着时间的推移而改变。
下面是描述结果中预期内容的代码:
class TabsViewModel: ObservableObject {
@Published var items = [-2, -1, 0, 1, 2]
@Published var selectedItem = 2 {
didSet {
if let index = items.firstIndex(of: selectedItem), index >= items.count - 2 {
items = items + [items.last! + 1]
items.removeFirst()
}
if let index = items.firstIndex(of: selectedItem), index <= 1 {
items = [items.first! - 1] + items
items.removeLast()
}
}
}
}
struct TabsView: View {
@StateObject var vm = TabsViewModel()
var body: some View {
TabView(selection: $vm.selectedItem) {
ForEach(vm.items, id: \.self) { item in
Text(item.description)
.frame(minWidth: 0,
maxWidth: .infinity,
minHeight: 0,
maxHeight: .infinity,
alignment: .topLeading
)
.background(Color(hue: .random(in: 0...0.99), saturation: .random(in: 0...0.99), brightness: 0.5))
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
}
}
在这种情况下,当您尝试转到下一页或上一页时,动画中断,原始页面立即返回到其位置。
有没有可能在没有UIKit和第三方框架的帮助下,用TabView实现这一点?
我猜测可能的解决方案之一是在过渡动画完成时更改数据源,但我无法在SwiftUI中找到这样做的方法。
我猜的对吗?也许还有其他更优雅的方法来实现此功能,我的观点是错误的。
2条答案
按热度按时间x8diyxa71#
任务本身可以使用SwiftUIPager框架来解决。
文档使用
onPageChanged
来更新数据源,但是在数组的中间或开头插入一个值会使应用程序崩溃。polkgigr2#
对于那些正在寻找没有外部依赖的简单解决方案的人:我刚刚实现了自己的变体,基于
TabView
和.page
选项卡视图样式。它基于这样的想法:你有两个函数before()
和after()
,它们返回index(!)的当前所选页面(存储在selection
中)之前或之后的页面。有一个view
方法,它返回给定页面索引的视图。所以基本上总是有三个页面:* 前一页 (标记为-1)、 当前页 *(标记为0)和 * 下一页 *(标记为1)。当用户滑动页面(=
TabView
内容)时,currentTab
将更新为TabView(selection:)
。然后,当 * 当前 * 页面不在屏幕上时(=调用onDisappear
),此currentTab
将传播到selection
变量,再次将currentTab
更新为0。由于新设置的selection
,重新生成 previous、current 和 next 页。解决方案是使用Swift泛型。我一直在使用
Int
和Date
索引来呈现页面。下面是一个如何使用它的例子:这是一个颜色数组,当你越过边界(=数组的开始或结束)时,它会“循环”/“滚动”,所以你可以在任何方向上永远滑动颜色。
类似的代码可以用于在日历或无尽的约会列表中滑动。