【问题标题】:How to change the status bar text color in SwiftUI for each TabView Item?如何在 SwiftUI 中为每个 TabView 项更改状态栏文本颜色?
【发布时间】:2021-03-25 17:57:45
【问题描述】:

您可以找到许多 (UIKit) 解决方案来为 SwiftUI 视图设置状态栏的文本颜色。不幸的是,根据我的经验,这些解决方案在运行时似乎不能令人满意地用于 TabViews。

找到解决方案:

SwiftUI: Set Status Bar Color For a Specific View

How can I change the status bar text color per view in SwiftUI?

使用这些解决方案,您会很快发现在尝试在选项卡之间切换时,文本颜色并不总是设置正确。

不幸的是,Apple 目前似乎没有直接的解决方案让 SwiftUI 像使用 UIKit 那样更改每个视图的 UIStatusBarStyle。

我只是找不到在运行时更改每个选项卡的状态栏文本颜色的稳定方法。

【问题讨论】:

    标签: ios swiftui


    【解决方案1】:

    我阅读了其他解决方案,但没有尝试过。但以下工作,我也认为它可以让其他解决方案工作。

    1. 转到您的 Info.plist 并将 UIViewControllerBasedStatusBarAppearance 设置为 NO
    2. 从这里开始,我认为您提到的解决方案也可以工作。

    如果您不介意在代码中出现弃用警告,这也是一种选择:

    TabView {
        Text("1")
            .tabItem { Text("1") }
            .onAppear {
                UIApplication.shared.setStatusBarStyle(.lightContent, animated: false)
            }
    
        Text("2")
            .tabItem { Text("2") }
            .onAppear {
                UIApplication.shared.setStatusBarStyle(.darkContent, animated: true)
            }
    }
    

    setStatusBarStyle 已被弃用,因此它可能不是最佳选择。

    【讨论】:

      【解决方案2】:

      我现在可以自助了。我找到了一个解决方案,它采用了一种适用于 TabViews 的方法,基于:https://github.com/xavierdonnellon/swiftui-statusbarstyle

      我的完整代码示例,其中先前状态栏样式的状态在处理时被保存和恢复(在运行时密切关注状态栏样式层次结构很重要):

      ExampleApp.swift

      import SwiftUI
      
      @main
      struct ExampleApp: App {
          
          init() {
              //navigation bar
              let coloredNavAppearance = UINavigationBarAppearance()
              coloredNavAppearance.configureWithTransparentBackground()
              coloredNavAppearance.backgroundColor = .clear
              coloredNavAppearance.backgroundEffect = nil
              coloredNavAppearance.backgroundImage = UIImage()
              coloredNavAppearance.shadowImage = UIImage()
              coloredNavAppearance.shadowColor = .clear
              coloredNavAppearance.titleTextAttributes = [
                  .foregroundColor: UIColor.black
              ]
              coloredNavAppearance.largeTitleTextAttributes = [
                  .foregroundColor: UIColor.black
              ]
              
              UINavigationBar.appearance().standardAppearance = coloredNavAppearance
              UINavigationBar.appearance().scrollEdgeAppearance = coloredNavAppearance
              UINavigationBar.appearance().compactAppearance = coloredNavAppearance
              
          }
          
          var body: some Scene {
              WindowGroup {
                  RootView(content: {
                      ContentView()
                  })
              }
          }
      }
      

      UIApplication+StatusBarStyle.swift

      extension UIApplication {
          static var hostingController: HostingController<AnyView>? = nil
          
          static var statusBarStyleHierarchy: [UIStatusBarStyle] = []
          static var statusBarStyle: UIStatusBarStyle = .darkContent
          
          ///Sets the App to start at rootView
          func setHostingController(rootView: AnyView) {
              let hostingController = HostingController(rootView: AnyView(rootView))
              windows.first?.rootViewController = hostingController
              UIApplication.hostingController = hostingController
          }
          
          static func setStatusBarStyle(_ style: UIStatusBarStyle) {
              statusBarStyle = style
              hostingController?.setNeedsStatusBarAppearanceUpdate()
          }
      }
      
      class HostingController<Content: View>: UIHostingController<Content> {
          override var preferredStatusBarStyle: UIStatusBarStyle {
              return UIApplication.statusBarStyle
          }
      }
      
      ///By wrapping views in a RootView, they will become the app's main / primary view. This will enable setting the statusBarStyle.
      struct RootView<Content: View> : View {
          var content: Content
          
          init(@ViewBuilder content: () -> (Content)) {
              self.content = content()
          }
          
          var body:some View {
              EmptyView()
                  .onAppear {
                      UIApplication.shared.setHostingController(rootView: AnyView(content))
                  }
          }
      }
      

      ContentView.swift

      import SwiftUI
      
      struct ContentView: View {
          
          @State var tabRoute = TabRoute.green
          
          enum TabRoute: String, Identifiable {
              
              var id: String {
                  self.rawValue
              }
              
              case green, black, blue, purple
              
              static var all: [TabRoute] {
                  [.green, .black, .blue, .purple]
              }
              
              var bgColor: Color {
                  switch self {
                  case .green:
                      return .green
                      
                  case .black:
                      return .black
                      
                  case .blue:
                      return .blue
                      
                  case .purple:
                      return .purple
                      
                  }
              }
              
              var statusBarStyle: UIStatusBarStyle {
                  switch self {
                  case .black:
                      return .lightContent
                      
                  default:
                      return .darkContent
                      
                  }
              }
          }
          
          
          var body: some View {
              
              TabView(selection: $tabRoute) {
                  
                  ForEach(TabRoute.all) { route in
                      NavigationView {
                          ViewExample(isPresented: false, title: route.rawValue, bgColor: route.bgColor, statusBarStyle: route.statusBarStyle)
                              .navigationTitle(route.rawValue)
                              .navigationBarTitleDisplayMode(.inline)
                      }
                      .navigationViewStyle(StackNavigationViewStyle())
                      .tabItem {
                          Text(route.rawValue)
                      }
                      .tag(TabRoute(rawValue: route.rawValue))
                  }
                  
              }
              .edgesIgnoringSafeArea(.all)
          }
          
      }
      
      struct ViewExample: View {
          
          @Environment(\.presentationMode) var presentationMode
      
          @State private var sheetIsPresented = false
          
          @State  var isPresented: Bool
          
          var title: String
          
          var bgColor: Color
          
          @State var statusBarStyle: UIStatusBarStyle
          
          var body: some View {
              ZStack {
                  bgColor
              }
              .onAppear {
                  UIApplication.statusBarStyleHierarchy.append(statusBarStyle)
                  UIApplication.setStatusBarStyle(statusBarStyle)
              }
              .onDisappear {
                  guard UIApplication.statusBarStyleHierarchy.count > 1 else { return }
                  let style = UIApplication.statusBarStyleHierarchy[UIApplication.statusBarStyleHierarchy.count - 1]
                  UIApplication.statusBarStyleHierarchy.removeLast()
                  UIApplication.setStatusBarStyle(style)
              }
              .edgesIgnoringSafeArea(.all)
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-27
        • 1970-01-01
        • 2013-07-14
        • 2020-03-25
        • 1970-01-01
        相关资源
        最近更新 更多