【问题标题】:How to dynamically hide the status bar and the home indicator in SwiftUI?如何在 SwiftUI 中动态隐藏状态栏和主页指示器?
【发布时间】:2022-06-20 02:23:36
【问题描述】:

我正在开发一个分形时钟应用程序,该应用程序在其主视图中显示基于时钟指针的动画分形。我希望我的应用程序的用户能够进入全屏模式,其中所有不必要的 UI 都被暂时隐藏,只有动画仍然可见。我正在寻找的行为类似于 Apple 的 Photos 应用程序,其中可以点击当前显示的图像,以便导航栏、底部栏、状态栏和主页指示器淡出,直到再次点击图像。

隐藏导航栏和状态栏就像找到正确的视图修饰符来传递隐藏条件一样简单。但据我所知,目前 SwiftUI 无法在不引入 UIKit 的情况下隐藏主页指示器。

在 Stack Overflow 上,我发现 this solution by Casper Zandbergen 有条件地隐藏 home 指示器并将其用于我的项目。 它可以工作,但遗憾的是带来了一个不可接受的副作用:主视图现在不再延伸到状态栏和主页指示器下方,这有两个含义:

  1. 使用相关 SwiftUI 修改器隐藏状态栏时,主视图的空间会随着隐藏状态栏的高度而增长,从而中断分形动画的显示。
  2. 隐藏的主页指示器始终保留黑色底栏,以防止全屏显示主视图。

我希望有良好 UIKit 经验的人可以帮助我解决这个问题。请记住,我是 SwiftUI 的初学者,而且我基本上没有使用 UIKit 的经验。提前致谢!

import SwiftUI

struct ContentView: View {
    @StateObject var settings = Settings()
    
    @State private var showSettings = false
    @State private var hideUI = false
    
    var body: some View {
        NavigationView {
            GeometryReader { proxy in
                let radius = 0.5 * min(proxy.size.width, proxy.size.height) - 20
                FractalClockView(settings: settings, clockRadius: radius)
            }
            .ignoresSafeArea(.all)
            .toolbar {
                Button(
                    action: { showSettings.toggle() },
                    label: { Label("Settings", systemImage: "slider.horizontal.3") }
                )
                    .popover(isPresented: $showSettings) { SettingsView(settings: settings) }
            }
            .navigationBarTitleDisplayMode(.inline)
            .onTapGesture {
                withAnimation { hideUI.toggle() }
            }
            .navigationBarHidden(hideUI)
            .statusBar(hidden: hideUI)
            .prefersHomeIndicatorAutoHidden(hideUI) // Code by Amzd
        }
        .navigationViewStyle(.stack)
    }
}

【问题讨论】:

    标签: ios swiftui uikit


    【解决方案1】:

    通过完全切换到基于故事板的项目模板并通过自定义 UIHostingController 嵌入我的视图,如@ 987654321@。 在我通过使用 UIViewRepresentable 实例将宿主控制器重新集成到 SwiftUI 视图层次结构中之前,这肯定会导致处理安全区域的复杂性。

    通过自定义 UIHostingController 子类管理整个应用程序,更容易隐藏 home 指示器。尽管我很喜欢 SwiftUI,但我不得不意识到,由于目前的局限性,UIKit 是这里更好的选择。

    最终代码(上面链接的解决方案的优化版本):

    ViewController.swift

    import SwiftUI
    import UIKit
    
    struct HideUIPreferenceKey: PreferenceKey {
        static var defaultValue: Bool = false
        
        static func reduce(value: inout Bool, nextValue: () -> Bool) {
            value = nextValue() || value
        }
    }
    
    extension View {
        func userInterfaceHidden(_ value: Bool) -> some View {
            preference(key: HideUIPreferenceKey.self, value: value)
        }
    }
    
    class ViewController: UIHostingController<AnyView> {
        init() {
            weak var vc: ViewController? = nil
            super.init(
                rootView: AnyView(
                    ContentView()
                        .onPreferenceChange(HideUIPreferenceKey.self) {
                            vc?.userInterfaceHidden = $0
                        }
                )
            )
            vc = self
        }
    
        @objc required dynamic init?(coder: NSCoder) {
            weak var vc: ViewController? = nil
            super.init(
                coder: coder,
                rootView: AnyView(
                    ContentView()
                       .onPreferenceChange(HideUIPreferenceKey.self) {
                           vc?.userInterfaceHidden = $0
                       }
               )
            )
            vc = self
        }
        
        private var userInterfaceHidden = false {
            didSet { setNeedsUpdateOfHomeIndicatorAutoHidden() }
        }
        
        override var prefersStatusBarHidden: Bool {
            userInterfaceHidden
        }
        
        override var prefersHomeIndicatorAutoHidden: Bool {
            userInterfaceHidden
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-11-15
      • 2013-06-09
      • 2020-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多