【发布时间】:2022-11-23 07:30:19
【问题描述】:
当 SwiftUI 创建一个 SplitView 时,它会添加一个工具栏按钮来隐藏/显示主视图。我怎样才能检测到这种变化,以便我可以调整详细信息屏幕中的字体大小并优化使用所有空间?
我试过将 .onChange 与几何一起使用,但似乎无法正常工作。
【问题讨论】:
标签: swiftui master-detail splitview
当 SwiftUI 创建一个 SplitView 时,它会添加一个工具栏按钮来隐藏/显示主视图。我怎样才能检测到这种变化,以便我可以调整详细信息屏幕中的字体大小并优化使用所有空间?
我试过将 .onChange 与几何一起使用,但似乎无法正常工作。
【问题讨论】:
标签: swiftui master-detail splitview
在思考了一段时间之后,我得到了这个解决方案:
struct ContentView: View {
@State var isOpen = true
var body: some View {
NavigationView {
VStack{
Text("Primary")
.onUIKitAppear {
isOpen.toggle()
}
.onAppear{
print("hello")
isOpen.toggle()
}
.onDisappear{
isOpen.toggle()
print("hello: bye")
}
.navigationTitle("options")
}
Text("Secondary").font(isOpen ? .body : .title)
}.navigationViewStyle(.columns)
}
}
onUIKitAppear 是苹果建议的自定义extension,只有在视图呈现给用户https://developer.apple.com/forums/thread/655338?page=2后才执行
struct UIKitAppear: UIViewControllerRepresentable {
let action: () -> Void
func makeUIViewController(context: Context) -> UIAppearViewController {
let vc = UIAppearViewController()
vc.delegate = context.coordinator
return vc
}
func makeCoordinator() -> Coordinator {
Coordinator(action: self.action)
}
func updateUIViewController(_ controller: UIAppearViewController, context: Context) {}
class Coordinator: ActionRepresentable {
var action: () -> Void
init(action: @escaping () -> Void) {
self.action = action
}
func remoteAction() {
action()
}
}
}
protocol ActionRepresentable: AnyObject {
func remoteAction()
}
class UIAppearViewController: UIViewController {
weak var delegate: ActionRepresentable?
var savedView: UIView?
override func viewDidLoad() {
self.savedView = UILabel()
if let _view = self.savedView {
view.addSubview(_view)
}
}
override func viewDidAppear(_ animated: Bool) {
delegate?.remoteAction()
}
override func viewDidDisappear(_ animated: Bool) {
view.removeFromSuperview()
savedView?.removeFromSuperview()
}
}
public extension View {
func onUIKitAppear(_ perform: @escaping () -> Void) -> some View {
self.background(UIKitAppear(action: perform))
}
}
【讨论】:
如果您使用的是 iOS 16,则可以使用 NavigationSplitView 和 NavigationSplitViewVisibility
例子:
struct MySplitView: View {
@State private var columnVisibility: NavigationSplitViewVisibility = .all
var bothAreShown: Bool { columnVisibility != .detailOnly }
var body: some View {
NavigationSplitView(columnVisibility: $columnVisibility) {
Text("Master Column")
} detail: {
Text("Detail Column")
Text(bothAreShown ? "Both are shown" : "Just detail shown")
}
}
}
【讨论】: