我在 SwiftUI 中有一个自定义 TabBar,可以用动画显示/隐藏。问题在于隐藏 TabBar 时处理交互:
这是我的完整代码:
import SwiftUI
struct MainTabView: View {
@State private var selectedTab = 0
@State private var tabBarVisible = true
@State private var tabBarHeight: CGFloat = 0
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .bottom) {
// Main content
TabView(selection: $selectedTab) {
HomeView()
.tag(0)
FavoritesView()
.tag(1)
EmptyView()
.tag(2)
SettingsView()
.tag(3)
}
// Custom tab bar
VStack(spacing: 0) {
Spacer()
if tabBarVisible {
CustomTabBar(selectedTab: $selectedTab, tabbarVisible: $tabBarVisible)
.padding(.bottom, geometry.safeAreaInsets.bottom)
.transition(.move(edge: .bottom))
.background(
GeometryReader { geo in
Color.clear.onAppear {
tabBarHeight = geo.size.height
}
}
)
}
}
}
.ignoresSafeArea(edges: .bottom)
}
.environment(\.tabBarVisibility, $tabBarVisible)
}
}
struct CustomTabBar: View {
@Binding var selectedTab: Int
@Binding var tabbarVisible: Bool
var body: some View {
HStack(spacing: 0) {
TabBarButton(imageName: "house", isSelected: selectedTab == 0, action: { selectedTab = 0 })
TabBarButton(imageName: "magnifyingglass", isSelected: selectedTab == 1, action: { selectedTab = 1 })
TabBarButton(imageName: "bell", isSelected: selectedTab == 2, action: { selectedTab = 2 })
TabBarButton(imageName: "person", isSelected: selectedTab == 3, action: { selectedTab = 3 })
}
.padding(8)
.background(
Color.white
.shadow(color: Color.black.opacity(0.1), radius: 8, x: 0, y: -4)
)
.cornerRadius(25)
.padding(.horizontal)
}
}
struct TabBarButton: View {
let imageName: String
let isSelected: Bool
let action: () -> Void
var body: some View {
Button(action: action) {
Image(systemName: imageName)
.font(.system(size: 24))
.foregroundColor(isSelected ? .white : .black.opacity(0.65))
.frame(maxWidth: .infinity)
.padding(.vertical, 10)
.background(isSelected ? Color.purple.opacity(0.7) : Color.clear)
.clipShape(Capsule())
}
}
}
// Environment key for tab bar visibility
struct TabBarVisibilityKey: EnvironmentKey {
static let defaultValue: Binding<Bool> = .constant(true)
}
extension EnvironmentValues {
var tabBarVisibility: Binding<Bool> {
get { self[TabBarVisibilityKey.self] }
set { self[TabBarVisibilityKey.self] = newValue }
}
}
struct ContentView: View {
var body: some View {
MainTabView()
}
}
struct DetailView: View {
@Environment(\.tabBarVisibility) var tabBarVisibility
var body: some View {
ScrollView {
VStack {
// Content here
Button("Toggle TabBar") {
withAnimation(.easeInOut) {
tabBarVisibility.wrappedValue.toggle()
}
}
}
}
.onAppear {
// Hide tab bar when view appears
withAnimation(.easeInOut) {
tabBarVisibility.wrappedValue = false
}
}
.onDisappear {
// Show tab bar when view disappears
withAnimation(.easeInOut) {
tabBarVisibility.wrappedValue = true
}
}
}
}
当 TabBar 可见时:
当 TabBar 隐藏时:
任何人都可以建议一种方法来实现这一目标吗?我特别需要防止 TabBar 区域在隐藏时与其交互,同时允许其他 UI 元素仍然可以交互。
if !tabBarVisible {
Rectangle()
.fill(Color.clear)
.ignoresSafeArea()
.contentShape(Rectangle())
.onTapGesture { }
}
问题:这会阻止该区域的所有交互,包括合法的 UI 元素。
if !tabBarVisible {
CustomTabBar(selectedTab: $selectedTab, tabbarVisible: $tabBarVisible)
.opacity(0)
.allowsHitTesting(false)
}
问题:这根本不会阻止任何交互。
if !tabBarVisible {
HStack(spacing: 0) {
// Same buttons as CustomTabBar but with empty actions
}
.opacity(0)
}
问题:仍然允许交互通过。
我认为即使自定义选项卡栏隐藏也可以更改选项卡的原因是因为 native 选项卡栏仍然存在。您看不到它是因为没有与您的视图关联的
TabItem
。
因此,要确认问题,请尝试添加一些
TabItem
:
TabView(selection: $selectedTab) {
HomeView()
.tabItem { Text("Home") }
.tag(0)
FavoritesView()
.tabItem { Text("Favourites") }
.tag(1)
// ...
}
要隐藏本机选项卡栏,请将
.toolbarVisibility(.hidden, for: .tabBar)
添加到每个子视图(并删除上面添加的 TabItem
):
TabView(selection: $selectedTab) {
HomeView()
.toolbarVisibility(.hidden, for: .tabBar)
.tag(0)
FavoritesView()
.toolbarVisibility(.hidden, for: .tabBar)
.tag(1)
// ...
}