首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在SwiftUI中动态隐藏状态栏和主指示器?

如何在SwiftUI中动态隐藏状态栏和主指示器?
EN

Stack Overflow用户
提问于 2022-01-23 09:37:48
回答 1查看 768关注 0票数 0

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

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

在堆栈溢出时,我找到了用于有条件隐藏主指示器的this solution by Casper Zandbergen,并将其用于我的项目。它起作用了,但不幸的是,它带来了一个不可接受的副作用:主视图现在不再扩展到状态栏和主指示器下面,这两种情况有两个含义:

  1. 在使用相关的SwiftUI修饰符隐藏状态栏时,主视图的空间随着隐藏状态栏的高度而增长,中断了分形动画的显示。
  2. 代替隐藏的家庭指示器总是保持黑色的底部条,阻止主视图的全屏显示。

我希望有不错的UIKit经验的人能帮我这个忙。请记住,我是SwiftUI的初学者,我基本上没有使用UIKit的经验。提前感谢!

代码语言:javascript
运行
复制
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)
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-19 18:23:36

通过完全切换到基于故事板的项目模板,并按照SwiftUI中描述的那样,通过自定义UIHostingController嵌入视图,我能够解决UIHostingController视图不能扩展到状态栏和主指示器的安全区域内的问题。在我将托管控制器重新集成到SwiftUI视图层次结构之前,我用一个UIViewRepresentable实例包装了它,这肯定导致了处理安全区域的复杂性。

通过定制的UIHostingController子类来管理整个应用程序,可以更容易地隐藏家庭指示器。尽管我非常喜欢SwiftUI,但我不得不意识到,由于其目前的局限性,UIKit在这里是更好的选择。

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

ViewController.swift

代码语言:javascript
运行
复制
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
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70820790

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档