|
import SwiftUI |
|
|
|
var hostingController: UIViewController? |
|
|
|
func getUISplitViewController() -> UISplitViewController { |
|
if hostingController?.children.count == 0 { |
|
fatalError() |
|
} |
|
guard let split = hostingController?.children[0] as? UISplitViewController else { |
|
fatalError() |
|
} |
|
return split |
|
} |
|
|
|
func isCollapsed() -> Bool { |
|
getUISplitViewController().isCollapsed |
|
} |
|
|
|
func isAllVisible() -> Bool { |
|
getUISplitViewController().displayMode == .allVisible |
|
} |
|
|
|
func showPrimary() { |
|
let split = getUISplitViewController() |
|
if split.isCollapsed { |
|
return |
|
} |
|
UIView.animate(withDuration: 0.3, animations: { |
|
split.preferredDisplayMode = .primaryOverlay |
|
}) { _ in |
|
split.preferredDisplayMode = .automatic |
|
} |
|
} |
|
|
|
func hidePrimary() { |
|
let split = getUISplitViewController() |
|
if split.isCollapsed || split.displayMode == .allVisible { |
|
return |
|
} |
|
DispatchQueue.main.async { |
|
split.preferredDisplayMode = .primaryHidden |
|
} |
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { |
|
split.preferredDisplayMode = .automatic |
|
} |
|
} |
|
|
|
// ===== |
|
|
|
struct DetailView: View { |
|
var item: Int |
|
var body: some View { |
|
VStack { |
|
Text("Item \(self.item)") |
|
if !isCollapsed() && !isAllVisible() { |
|
Button(action: showPrimary) { |
|
Image(systemName: "sidebar.left") |
|
} |
|
} |
|
} |
|
.onAppear { |
|
hidePrimary() |
|
} |
|
} |
|
} |
|
|
|
struct ContentView: View { |
|
var body: some View { |
|
NavigationView { |
|
List { |
|
ForEach(1...100, id: \.self) { i in |
|
NavigationLink(destination: DetailView(item: i)) { |
|
Text("Item \(i)") |
|
} |
|
} |
|
} |
|
VStack { |
|
Button(action: showPrimary) { |
|
Image(systemName: "sidebar.left") |
|
} |
|
Text("or swipe") |
|
} |
|
} |
|
} |
|
} |
|
|
|
import PlaygroundSupport |
|
hostingController = UIHostingController(rootView: ContentView()) |
|
PlaygroundPage.current.setLiveView(hostingController!) |