ios - 将 SwiftUI View 覆盖在所有其他 View (包括工作表)上

标签 ios swift swiftui

我见过关于此问题的讨论涉及 UIKit,但最近没有看到涉及 SwiftUI 的讨论。

我有一个主从风格的应用程序,需要两个 float 按钮,这些按钮应在应用程序中始终可见。

设置按钮:点击时将通过一些切换取消隐藏另一个覆盖层 添加记录按钮:点击时将通过 @State 变量显示工作表,再次点击时将关闭该工作表。

如果我将按钮设置为导航 View 上的覆盖层,那么当它呈现工作表时,它们就会被插入背景。这并不特别令人惊讶,但这不是设计中所要求的行为。

第一种方法 - NavigationView() 上的 .overlay

struct ContentView: View {
    @State var addRecordPresented: Bool = false
      var body: some View {

        NavigationView {
            VStack {
                SomeView()
                AnotherView()
                    .sheet(isPresented: $addRecordPresented, onDismiss: {self.addRecordPresented = false}) {AddRecordView()}
            }
            .overlay(NewRecordButton(isOn: $addRecordPresented).onTapGesture{self.addRecordPresented.toggle()}, alignment: .bottomTrailing)
        }
    }
}

第二种方法 - 覆盖为第二个 UIWindow

然后我再次开始并尝试在 SceneDelegate 中创建第二个 UIWindow,其中包含一个在 UIHostingController 中托管 SwiftUI View 的 ViewController,但是我没有成功尝试覆盖以允许两个按钮都可点击,但对于其他点击传递到覆盖窗口后面的窗口。

数据流内容被删除,这只是试图呈现一个 float 的可点击圆圈,点击时将在绿色和红色之间切换,并且在主内容 View 中有一个紫色方 block ,点击时将呈现黄色表。该圆圈正确地漂浮在纸张顶部,但从不响应点击。

在场景委托(delegate)中:

    var window: UIWindow?
    var wimdow2: UIWindow2?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

           (...)


        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: contentView)
            self.window = window

            window.windowLevel = .normal
            window.makeKeyAndVisible()

            let window2 = UIWindow2(windowScene: windowScene)
            window2.rootViewController = OverlayViewController()

            self.window2 = window2
            window2.windowLevel = .normal+1
            window2.isHidden = false
        }
    }


            (...)


        class UIWindow2: UIWindow {

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {

        let hitView = super.hitTest(point, with: event)

        if hitView != self {
            return nil
        }
        return hitView
    }
}

在 ViewController 文件中:

import UIKit
import SwiftUI

class OverlayViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()


        let overlayView = UIHostingController(rootView: NewRecordButton())
        addChild(overlayView)

        overlayView.view.backgroundColor = UIColor.clear
        overlayView.view.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
        overlayView.view.isUserInteractionEnabled = true

        self.view.addSubview(overlayView.view)
        overlayView.didMove(toParent: self)

    }

}

struct NewRecordButton: View {
    @State var color = false
    var body: some View {
        Circle().foregroundColor(color ? .green : .red).frame(width: 50, height: 50).onTapGesture {
            self.color.toggle()
            print("tapped circle")
        }
    }
}

主内容窗口中的普通 swiftUI View :

import SwiftUI

struct ContentView: View {
    @State var show: Bool = false
    var body: some View {

        NavigationView {
            VStack {
                Rectangle().frame(width: 100, height: 100).foregroundColor(.purple).onTapGesture {self.show.toggle()}
                Text("Tap for Yellow").sheet(isPresented: $show, content: {Color.yellow}
                )
            }
        }
    }
}

任何有关如何正确实现这一点的建议或引用将不胜感激!

最佳答案

这在技术上是可行的,但我设法让它发挥作用的方式是脆弱且丑陋的。 这个想法是

  1. 将按钮添加为应用关键窗口的子窗口,并且
  2. 每次提交表格时都将其放在前面。 具体来说,在工作表演示开始后,必须将其置于前面并延迟一些。

即:

  1. UIApplication.shared.windows.first?.addSubview(settingsButton)
  2. 当任何工作表即将显示时,通知 settingsButton 的所有者,以便它将该按钮置于前面:

DispatchQueue.main.asyncAfter(截止日期:DispatchTime.now()+ 0.1){ UIApplication.shared.windows.first?.bringSubviewToFront(settingsButton) }

关于ios - 将 SwiftUI View 覆盖在所有其他 View (包括工作表)上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59277120/

相关文章:

ios - SKTileMapNode:检测触摸的 Tile?

ios - Xcode Apple Mach-O 链接器错误 1

swift - 在 SpriteKit Swift 中移动相机

uitableview - TableView 重新加载不适用于 SwiftUI 中的 UIViewRepresentable

ios - SwiftUI:如何更改@Published 对象值。更改已发布变量的值不起作用

ios - 如何以字典流形式获取输出 - 套接字

ios - 使用回调重现 UIAlertViewController

swift - 快速连接字符时出错

ios - 如何在点击 Swift4 时关闭 UIView

swiftui - 如何使底部按钮跟随 SwiftUI 中的键盘显示