SwiftUI - 将可滚动的 TabBar 转换为静止的 TabBar
SwiftUI - Convert a scrollable TabBar into a still TabBar
目前我所遵循的教程存在问题,该教程使用 SwiftUI 创建了带下划线的选项卡栏。在当前阶段,当视图更改时,选项卡栏会随着滚动视图一起滚动,但是,我希望按钮保持空闲状态,作为正常(仍在运行)带下划线的选项卡栏,而不是发生这种情况。这是当前滑动视图时的样子:
请注意,当标签更改时,标签在标签栏内如何更改时,标签滚动滚动。我试过删除标签栏的滚动视图,但似乎无法弄清楚如何让它在屏幕内保持固定。
教程中的代码如下所示:
import SwiftUI
struct ContentView: View {
@State var currentTab: Int = 0
var body: some View {
ZStack(alignment: .top) {
TabView(selection: self.$currentTab) {
View1().tag(0)
View2().tag(1)
}
.tabViewStyle(.page(indexDisplayMode: .never))
.edgesIgnoringSafeArea(.all)
TabBarView(currentTab: self.$currentTab)
}
}
}
struct TabBarView: View {
@Binding var currentTab: Int
@Namespace var namespace
var tabBarOptions: [String] = ["View 1", "View 2"]
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 20) {
ForEach(Array(zip(self.tabBarOptions.indices,
self.tabBarOptions)),
id: \.0,
content: {
index, name in
TabBarItem(currentTab: self.$currentTab,
namespace: namespace.self,
tabBarItemName: name,
tab: index)
})
}
.padding(.horizontal)
}
.background(Color.white)
.frame(height: 80)
.edgesIgnoringSafeArea(.all)
}
}
struct TabBarItem: View {
@Binding var currentTab: Int
let namespace: Namespace.ID
var tabBarItemName: String
var tab: Int
var body: some View {
Button {
self.currentTab = tab
} label: {
VStack {
Spacer()
Text(tabBarItemName)
if currentTab == tab {
Color.black
.frame(height: 2)
.matchedGeometryEffect(id: "underline",
in: namespace,
properties: .frame)
} else {
Color.clear.frame(height: 2)
}
}
.animation(.spring(), value: self.currentTab)
}
.buttonStyle(.plain)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
帮助解决此问题将不胜感激!谢谢!!
试试这个代码。这应该解决你的问题。主要问题是您使用了 ZStack 而不是 VStack。之后,只需 fiddle 围绕您在 VStack 中构建的元素的间距和定位。
让我知道它是否创建了您想要的结果。
import SwiftUI
struct ContentView: View {
@State var currentTab: Int = 0
var body: some View {
VStack(alignment: .center, spacing: 0) {
TabBarView(currentTab: self.$currentTab)
TabView(selection: self.$currentTab) {
Text("This is view 1").tag(0)
Text("This is view 2").tag(1)
}
.tabViewStyle(.page(indexDisplayMode: .never))
.background(Color.secondary) // <<<< Remove
}
.edgesIgnoringSafeArea(.all)
}
}
struct TabBarView: View {
@Binding var currentTab: Int
@Namespace var namespace
var tabBarOptions: [String] = ["View 1", "View 2"]
var body: some View {
HStack(spacing: 20) {
ForEach(Array(zip(self.tabBarOptions.indices,
self.tabBarOptions)),
id: \.0,
content: {
index, name in
TabBarItem(currentTab: self.$currentTab,
namespace: namespace.self,
tabBarItemName: name,
tab: index)
})
}
.padding(.horizontal)
.background(Color.orange) // <<<< Remove
.frame(height: 80)
}
}
struct TabBarItem: View {
@Binding var currentTab: Int
let namespace: Namespace.ID
var tabBarItemName: String
var tab: Int
var body: some View {
Button {
self.currentTab = tab
} label: {
VStack {
Spacer()
Text(tabBarItemName)
if currentTab == tab {
Color.black
.frame(height: 2)
.matchedGeometryEffect(id: "underline",
in: namespace,
properties: .frame)
} else {
Color.clear.frame(height: 2)
}
}
.animation(.spring(), value: self.currentTab)
}
.buttonStyle(.plain)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
目前我所遵循的教程存在问题,该教程使用 SwiftUI 创建了带下划线的选项卡栏。在当前阶段,当视图更改时,选项卡栏会随着滚动视图一起滚动,但是,我希望按钮保持空闲状态,作为正常(仍在运行)带下划线的选项卡栏,而不是发生这种情况。这是当前滑动视图时的样子:
请注意,当标签更改时,标签在标签栏内如何更改时,标签滚动滚动。我试过删除标签栏的滚动视图,但似乎无法弄清楚如何让它在屏幕内保持固定。
教程中的代码如下所示:
import SwiftUI
struct ContentView: View {
@State var currentTab: Int = 0
var body: some View {
ZStack(alignment: .top) {
TabView(selection: self.$currentTab) {
View1().tag(0)
View2().tag(1)
}
.tabViewStyle(.page(indexDisplayMode: .never))
.edgesIgnoringSafeArea(.all)
TabBarView(currentTab: self.$currentTab)
}
}
}
struct TabBarView: View {
@Binding var currentTab: Int
@Namespace var namespace
var tabBarOptions: [String] = ["View 1", "View 2"]
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 20) {
ForEach(Array(zip(self.tabBarOptions.indices,
self.tabBarOptions)),
id: \.0,
content: {
index, name in
TabBarItem(currentTab: self.$currentTab,
namespace: namespace.self,
tabBarItemName: name,
tab: index)
})
}
.padding(.horizontal)
}
.background(Color.white)
.frame(height: 80)
.edgesIgnoringSafeArea(.all)
}
}
struct TabBarItem: View {
@Binding var currentTab: Int
let namespace: Namespace.ID
var tabBarItemName: String
var tab: Int
var body: some View {
Button {
self.currentTab = tab
} label: {
VStack {
Spacer()
Text(tabBarItemName)
if currentTab == tab {
Color.black
.frame(height: 2)
.matchedGeometryEffect(id: "underline",
in: namespace,
properties: .frame)
} else {
Color.clear.frame(height: 2)
}
}
.animation(.spring(), value: self.currentTab)
}
.buttonStyle(.plain)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
帮助解决此问题将不胜感激!谢谢!!
试试这个代码。这应该解决你的问题。主要问题是您使用了 ZStack 而不是 VStack。之后,只需 fiddle 围绕您在 VStack 中构建的元素的间距和定位。 让我知道它是否创建了您想要的结果。
import SwiftUI
struct ContentView: View {
@State var currentTab: Int = 0
var body: some View {
VStack(alignment: .center, spacing: 0) {
TabBarView(currentTab: self.$currentTab)
TabView(selection: self.$currentTab) {
Text("This is view 1").tag(0)
Text("This is view 2").tag(1)
}
.tabViewStyle(.page(indexDisplayMode: .never))
.background(Color.secondary) // <<<< Remove
}
.edgesIgnoringSafeArea(.all)
}
}
struct TabBarView: View {
@Binding var currentTab: Int
@Namespace var namespace
var tabBarOptions: [String] = ["View 1", "View 2"]
var body: some View {
HStack(spacing: 20) {
ForEach(Array(zip(self.tabBarOptions.indices,
self.tabBarOptions)),
id: \.0,
content: {
index, name in
TabBarItem(currentTab: self.$currentTab,
namespace: namespace.self,
tabBarItemName: name,
tab: index)
})
}
.padding(.horizontal)
.background(Color.orange) // <<<< Remove
.frame(height: 80)
}
}
struct TabBarItem: View {
@Binding var currentTab: Int
let namespace: Namespace.ID
var tabBarItemName: String
var tab: Int
var body: some View {
Button {
self.currentTab = tab
} label: {
VStack {
Spacer()
Text(tabBarItemName)
if currentTab == tab {
Color.black
.frame(height: 2)
.matchedGeometryEffect(id: "underline",
in: namespace,
properties: .frame)
} else {
Color.clear.frame(height: 2)
}
}
.animation(.spring(), value: self.currentTab)
}
.buttonStyle(.plain)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}