如何在 swiftUi 中启用可滑动标签视图和底部导航
How to enable both wipe able tabview and bottom navigator in swiftUi
我是 iOS 和 swiftUi 的新手。当我尝试将 tabview 显示为默认但又希望我的 tabview 是可擦除的时,我被卡住了。
我已经知道我们可以通过添加 tabViewStyle 使 tabview 可以滑动,但是底部的导航器将消失。
.tabViewStyle(.page(indexDisplayMode: .never))
我能想到的解决方案是在底部添加一个新的视图并像导航器一样自定义,希望有人知道其他更好的解决方案。
谢谢!
一种可能的方法是通过匹配选择和对齐内容高度来使用两个同步的 TabView
。另请参阅内联评论。
测试 Xcode 13.2 / iOS 15.2
struct TestTwoTabViews: View {
@State private var selection1: Int = 1
@State private var selection2: Int = 1
// to make 2d TabView as height as content view of 1st TabView
@State private var viewHeight = CGFloat.infinity
var body: some View {
ZStack(alignment: .top) {
// responsible for bottom Tabs
TabView(selection: $selection1) {
Color.clear
.background(GeometryReader {
// read 1st content height
Color.clear.preference(key: ViewHeightKey.self,
value: [=10=].frame(in: .local).size.height)
})
.tabItem{Image(systemName: "1.square")}.tag(1)
Color.clear
.tabItem{Image(systemName: "2.square")}.tag(2)
Color.clear
.tabItem{Image(systemName: "3.square")}.tag(3)
}
// responsible for paging
TabView(selection: $selection2) {
Color.yellow.overlay(Text("First"))
.tag(1)
Color.green.overlay(Text("Second"))
.tag(2)
Color.blue.overlay(Text("Third"))
.tag(3)
}
.tabViewStyle(.page(indexDisplayMode: .never))
.frame(maxHeight: viewHeight) // content height
}
.onPreferenceChange(ViewHeightKey.self) {
self.viewHeight = [=10=] // apply content height
}
.onChange(of: selection1) {
selection2 = [=10=] // sync second
}
.onChange(of: selection2) {
selection1 = [=10=] // sync first
}
}
}
struct ViewHeightKey: PreferenceKey {
static var defaultValue: CGFloat { 0 }
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = value + nextValue()
}
}
我是 iOS 和 swiftUi 的新手。当我尝试将 tabview 显示为默认但又希望我的 tabview 是可擦除的时,我被卡住了。 我已经知道我们可以通过添加 tabViewStyle 使 tabview 可以滑动,但是底部的导航器将消失。
.tabViewStyle(.page(indexDisplayMode: .never))
我能想到的解决方案是在底部添加一个新的视图并像导航器一样自定义,希望有人知道其他更好的解决方案。 谢谢!
一种可能的方法是通过匹配选择和对齐内容高度来使用两个同步的 TabView
。另请参阅内联评论。
测试 Xcode 13.2 / iOS 15.2
struct TestTwoTabViews: View {
@State private var selection1: Int = 1
@State private var selection2: Int = 1
// to make 2d TabView as height as content view of 1st TabView
@State private var viewHeight = CGFloat.infinity
var body: some View {
ZStack(alignment: .top) {
// responsible for bottom Tabs
TabView(selection: $selection1) {
Color.clear
.background(GeometryReader {
// read 1st content height
Color.clear.preference(key: ViewHeightKey.self,
value: [=10=].frame(in: .local).size.height)
})
.tabItem{Image(systemName: "1.square")}.tag(1)
Color.clear
.tabItem{Image(systemName: "2.square")}.tag(2)
Color.clear
.tabItem{Image(systemName: "3.square")}.tag(3)
}
// responsible for paging
TabView(selection: $selection2) {
Color.yellow.overlay(Text("First"))
.tag(1)
Color.green.overlay(Text("Second"))
.tag(2)
Color.blue.overlay(Text("Third"))
.tag(3)
}
.tabViewStyle(.page(indexDisplayMode: .never))
.frame(maxHeight: viewHeight) // content height
}
.onPreferenceChange(ViewHeightKey.self) {
self.viewHeight = [=10=] // apply content height
}
.onChange(of: selection1) {
selection2 = [=10=] // sync second
}
.onChange(of: selection2) {
selection1 = [=10=] // sync first
}
}
}
struct ViewHeightKey: PreferenceKey {
static var defaultValue: CGFloat { 0 }
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = value + nextValue()
}
}