SwiftUI 在子视图中隐藏 TabBar

Dyn*_*erg 17 xcode swift ios13 swiftui

我正在使用 SwiftUI,但 TabBar 有一些问题。我想隐藏特定子视图上的 TabBar。

试过

UITabBar.appearance().isHidden = true
Run Code Online (Sandbox Code Playgroud)

它仅适用于 TabView 中的直接视图。但是当我把它放在子视图中时它不起作用。

有没有人解决这个问题?

谢谢。

use*_*510 59

iOS 16 原生方式

.toolbar(.hidden, for: .tabBar)

  • 不幸的是,当向后导航时,直到导航转换完成后才显示选项卡栏。使用 UIKit 标签栏将与视图一起滑入 (15认同)
  • 是的!!!!!最后:D (5认同)
  • 我们生活在辉煌的日子里 (4认同)
  • 这并不能真正解决问题,因为您在 NavigationView 中使用 TabView。这不是两者一起使用的方式,并且会导致更多问题。 (2认同)

Jac*_*ack 12

在此输入图像描述

要在跳到下一个屏幕时隐藏 TabBar,我们只需将其放置NavigationView到正确的位置即可。确保嵌入TabView内部,以便为两个选项卡NavigationView创建唯一的。Navigationview

如此处所述https://janeshswift.com/ios/swiftui/how-to-hide-tabbar-on-push-with-swiftui/

import SwiftUI

struct TabBarView: View {
    
    @State var tabSelection: Int = 0
    @State var tabArray = ["Profile", "Settings"]
    
    var body: some View {
        NavigationView {
            TabView(selection: $tabSelection){
                ForEach(0 ..< tabArray.count, id: \.self) { indexValue in
                    NavigationLink(destination: DetailView()){
                        VStack{
                            Text("\(tabArray[indexValue]) tab -- Click to jump next view")
                        }
                    }
                    .tabItem {
                        Image(systemName: "\(indexValue).circle.fill")
                        Text(tabArray[indexValue])
                    }
                    .tag(indexValue)
                    
                }
            }
            .navigationBarTitle(tabArray[tabSelection])
        }
    }
}
struct DetailView: View {
    var body: some View {
        Text("Detail View")
            .navigationBarTitle("NavigatedView")
            .navigationBarTitleDisplayMode(.inline)
            .navigationTitle("helllo")
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 11

iOS 15解决方案

除了 SwiftUI.TabView 中的视图修饰符之外,此解决方案效果良好。由于我的 TabView 位于符合的结构中App,因此看起来UITabBar连接的场景中仍然没有任何子视图。

使用下面的代码,您只需要在 SwiftUI.View 中使用showTabBar()或。hiddenTabBar()

extension UIApplication {
    var key: UIWindow? {
        self.connectedScenes
            .map({$0 as? UIWindowScene})
            .compactMap({$0})
            .first?
            .windows
            .filter({$0.isKeyWindow})
            .first
    }
}


extension UIView {
    func allSubviews() -> [UIView] {
        var subs = self.subviews
        for subview in self.subviews {
            let rec = subview.allSubviews()
            subs.append(contentsOf: rec)
        }
        return subs
    }
}
    

struct TabBarModifier {
    static func showTabBar() {
        UIApplication.shared.key?.allSubviews().forEach({ subView in
            if let view = subView as? UITabBar {
                view.isHidden = false
            }
        })
    }
    
    static func hideTabBar() {
        UIApplication.shared.key?.allSubviews().forEach({ subView in
            if let view = subView as? UITabBar {
                view.isHidden = true
            }
        })
    }
}

struct ShowTabBar: ViewModifier {
    func body(content: Content) -> some View {
        return content.padding(.zero).onAppear {
            TabBarModifier.showTabBar()
        }
    }
}
struct HiddenTabBar: ViewModifier {
    func body(content: Content) -> some View {
        return content.padding(.zero).onAppear {
            TabBarModifier.hideTabBar()
        }
    }
}

extension View {
    
    func showTabBar() -> some View {
        return self.modifier(ShowTabBar())
    }

    func hiddenTabBar() -> some View {
        return self.modifier(HiddenTabBar())
    }
}
Run Code Online (Sandbox Code Playgroud)


spn*_*nkr 9

在 iOS 16 上

使用.toolbar(.hidden, for: .tabBar)

例如:

var body: some View {
    TabView {
        FirstView()
            .tabItem {
                Text("First tab")
            }
            .toolbar(.hidden, for: .tabBar)

        SecondView()
            .tabItem {
                Text("Second tab")
            }
            .toolbar(.hidden, for: .tabBar)
    }
}

Run Code Online (Sandbox Code Playgroud)

请注意,.toolbar(.hidden, for: .tabBar)应用于每个视图tabItem,而不是父视图。YMMV 如果您有不同的结构(如父导航视图等)


小智 7

iOS 14 简单解决方案

安装 Introspect SwiftPM:https : //github.com/siteline/SwiftUI-Introspect

var body: some View {
    List {
        -your code here-
    }
    
    .navigationBarTitle("Title", displayMode: .inline)
    .introspectTabBarController { (UITabBarController) in
        UITabBarController.tabBar.isHidden = true
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:您必须在父视图中重新启用 TabBar,否则它仍将处于隐藏状态。

.introspectTabBarController { (UITabBarController) in
            UITabBarController.tabBar.isHidden = false
}
Run Code Online (Sandbox Code Playgroud)


fak*_*iho 6

这里没有办法隐藏 TabView,所以我不得不在 ZStack 中添加 TabView,如下所示:

var body: some View {
    ZStack {
        TabView {
            TabBar1().environmentObject(self.userData)
                .tabItem {
                    Image(systemName: "1.square.fill")
                    Text("First")
            }
            TabBar2()
                .tabItem {
                    Image(systemName: "2.square.fill")
                    Text("Second")
            }
        }

        if self.userData.showFullScreen {
            FullScreen().environmentObject(self.userData)

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用户数据:

  final class UserData: ObservableObject {
    @Published var showFullScreen = false
}
Run Code Online (Sandbox Code Playgroud)

标签栏1:

struct TabBar1: View {
    @EnvironmentObject var userData: UserData

    var body: some View {
        Text("TabBar 1")
            .edgesIgnoringSafeArea(.all)
            .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
            .background(Color.green)
            .onTapGesture {
                self.userData.showFullScreen.toggle()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

全屏:

struct FullScreen: View {
    @EnvironmentObject var userData: UserData

    var body: some View {
        Text("FullScreen")
            .edgesIgnoringSafeArea(.all)
            .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
            .background(Color.red)
            .onTapGesture {
                self.userData.showFullScreen.toggle()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Github上查看完整代码

还有其他一些方法,但这取决于视图的结构


小智 5

我使用的基本思想是结合 ObservableObject 和 ZStack。我已经将 TabView 放入带有条件子视图演示的 ZStack 中。 它的样子。查看github repo


Tem*_*ian 5

它正在工作,只需要在主队列上调用更改

struct ShowTabBar: ViewModifier {
    func body(content: Content) -> some View {
        return content.padding(.zero).onAppear {
            DispatchQueue.main.async {
                Tool.showTabBar()
            }
        }
    }
}

struct HiddenTabBar: ViewModifier {
    func body(content: Content) -> some View {
        return content.padding(.zero).onAppear {
            DispatchQueue.main.async {
                Tool.hiddenTabBar()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

遍历窗口的allsubview隐藏UITabBar。您可以将其编写为 ViewModifier 并在 SwiftUI 中使用它或使用工具将其隐藏。这个方法对我有用。

    extension UIView {
        
        func allSubviews() -> [UIView] {
            var res = self.subviews
            for subview in self.subviews {
                let riz = subview.allSubviews()
                res.append(contentsOf: riz)
            }
            return res
        }
    }
    
    struct Tool {
        static func showTabBar() {
            UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.allSubviews().forEach({ (v) in
                if let view = v as? UITabBar {
                    view.isHidden = false
                }
            })
        }
        
        static func hiddenTabBar() {
            UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.allSubviews().forEach({ (v) in
                if let view = v as? UITabBar {
                    view.isHidden = true
                }
            })
        }
    }
    
    struct ShowTabBar: ViewModifier {
        func body(content: Content) -> some View {
            return content.padding(.zero).onAppear {
                Tool.showTabBar()
            }
        }
    }
    struct HiddenTabBar: ViewModifier {
        func body(content: Content) -> some View {
            return content.padding(.zero).onAppear {
                Tool.hiddenTabBar()
            }
        }
    }
    
    extension View {
        func showTabBar() -> some View {
            return self.modifier(ShowTabBar())
        }
        func hiddenTabBar() -> some View {
            return self.modifier(HiddenTabBar())
        }
    }
Run Code Online (Sandbox Code Playgroud)


Muh*_*bas 5

iOS 14

安装 Introspect SwiftPM:https : //github.com/siteline/SwiftUI-Introspect

struct SomeView: View{
    
    @State var uiTabarController: UITabBarController?
    
    var body: some View {
        List {
            -your code here-
        }
        
        .navigationBarTitle("Title", displayMode: .inline)
        .introspectTabBarController { (UITabBarController) in
            UITabBarController.tabBar.isHidden = true
            uiTabarController = UITabBarController
        }.onDisappear{
            uiTabarController?.tabBar.isHidden = false
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

在这段代码中uiTabarController,我们参考了UITabarController. 当我们回去时,我们Tabar再次启用了。所以,这就是为什么需要这样做。


Swi*_*ier 5

iOS 16

修饰符的使用.toolbar。创建类型的状态属性Visibility并从推送视图管理其值

第一视角

struct FirstTab: View {
    @State var tabBarVisibility: Visibility = .visible

    var body: some View {
        NavigationView {
            NavigationLink(destination: WidgetDetailView(tab: self)) {
                Text("test")
            }   
        }
        .toolbar(tabBarVisibility, for: .tabBar)
    }
}
Run Code Online (Sandbox Code Playgroud)

第二个视图

struct WidgetDetailView: View {
    var tab: FirstTab
    
    var body: some View {
        Rectangle()
            .foregroundColor(Color.red)
            .onAppear {
                tab.tabBarVisibility = .hidden
            }
            .onDisappear {
                tab.tabBarVisibility = .visible
            }
    }
}
Run Code Online (Sandbox Code Playgroud)