【发布时间】:2020-04-04 05:22:00
【问题描述】:
我看到过有关 UIKit 的讨论,但最近没有任何涉及 SwiftUI 的讨论。
我有一个 Master-Detail 风格的应用程序,它需要两个浮动按钮,这些按钮应该在应用程序中始终可见。
设置按钮:点击时将通过一些切换取消隐藏另一个叠加层 添加记录按钮:点击时将通过@State 变量显示工作表,再次点击时将关闭工作表。
如果我将按钮设置为 NavigationView 上的叠加层,它们会在显示工作表时被推到后台。这并不特别令人惊讶,但这不是设计中要求的行为。
第一种方法 - .overlay on NavigationView()
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,其中包含一个 ViewController,该 ViewController 在 UIHostingController 中托管 SwiftUI 视图,但是我没有成功尝试覆盖以允许两个按钮都可以点击,但对于其他点击被传递到覆盖窗口后面的窗口。
数据流的东西被删除了,这只是试图呈现一个浮动的可点击圆圈,点击时会在绿色和红色之间切换,并且在主内容视图中有一个紫色方块,点击时会显示黄色表格。圆圈正确浮动在工作表顶部,但从不响应点击。
在场景代理中:
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 视图:
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}
)
}
}
}
}
任何关于如何正确实施的建议或参考将不胜感激!
【问题讨论】: