Sie auszublenden reichte nicht: solange `mode` auf `tabSidebar` steht, gehört die Seitenleiste zur Darstellung, und das System stellte sie wieder her — mit eigenem Pfeil und eigenem Knopf, hinter unserer. Auf dem Simulator fiel das nicht auf, auf dem Mac standen beide da. Jetzt wird erst die Form auf `tabBar` gestellt und dann die Tableiste ausgeblendet. Damit gibt es keine Seitenleiste mehr, die zurückkommen könnte. Der Test setzt die Stellung der Leiste über ein Startargument, statt zu nehmen, was ein voriger Lauf hinterlassen hat — er fing sonst beim falschen Bild an. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
82 lines
3.6 KiB
Swift
82 lines
3.6 KiB
Swift
#if os(iOS)
|
|
import SwiftUI
|
|
import UIKit
|
|
|
|
/// Blendet die vom System gezeichnete Seitenleiste und Tableiste aus.
|
|
///
|
|
/// Der Grund ist das Aussehen, nicht das Verhalten. `UITabBarController`
|
|
/// zeichnet seine Seitenleiste auf dem iPad als schwebende Fläche und auf dem
|
|
/// Mac angeklebt am Fensterrand — und das lässt sich nicht umstellen.
|
|
/// `preferredLayout = .overlap` ist die dafür vorgesehene Bitte; macOS verwirft
|
|
/// sie stillschweigend. Gemessen, nicht vermutet.
|
|
///
|
|
/// Statt deshalb die ganze Navigation selbst zu bauen, bleibt der
|
|
/// `TabView` **stehen** und verliert nur sein Kleid: Auswahl, getrennte
|
|
/// Navigationsstapel je Eintrag, erhaltener Scrollstand beim Wechseln,
|
|
/// Zustandspflege — all das macht weiter das System. Gezeichnet wird darüber.
|
|
///
|
|
/// Dass das geht, war kein Ratschluss: derselbe Griff hat die Leiste
|
|
/// versuchsweise schon einmal verschwinden lassen.
|
|
struct TabChromeSuppressor: UIViewControllerRepresentable {
|
|
func makeUIViewController(context: Context) -> UIViewController { Probe() }
|
|
func updateUIViewController(_ controller: UIViewController, context: Context) {}
|
|
|
|
/// Ein Controller, der nichts zeigt und nur da ist, um im Baum zu stehen.
|
|
private final class Probe: UIViewController {
|
|
override func didMove(toParent parent: UIViewController?) {
|
|
super.didMove(toParent: parent)
|
|
suppress()
|
|
}
|
|
|
|
override func viewDidAppear(_ animated: Bool) {
|
|
super.viewDidAppear(animated)
|
|
// Ein zweites Mal: beim ersten Anhängen steht der Tab-Controller
|
|
// noch nicht zwingend im Baum.
|
|
suppress()
|
|
}
|
|
|
|
override func viewWillLayoutSubviews() {
|
|
super.viewWillLayoutSubviews()
|
|
// Und bei jedem Umbau: das System stellt die Leisten wieder her,
|
|
// wenn sich die Größenklasse ändert — beim Drehen etwa.
|
|
suppress()
|
|
}
|
|
|
|
private func suppress() {
|
|
guard let controller = Self.tabBarController(from: self) else { return }
|
|
|
|
// Erst die Form festlegen, dann ausblenden — und zwar auf die
|
|
// Tableiste, nicht auf die Seitenleiste.
|
|
//
|
|
// Nur `sidebar.isHidden = true` reichte nicht: auf dem Mac stand
|
|
// die System-Seitenleiste danach wieder da, mit eigenem Pfeil und
|
|
// eigenem Knopf, hinter unserer. Solange `mode` auf `tabSidebar`
|
|
// steht, gehört die Seitenleiste zur Darstellung und das System
|
|
// stellt sie wieder her. Steht `mode` auf `tabBar`, gibt es keine
|
|
// Seitenleiste mehr, die zurückkommen könnte — und die Tableiste
|
|
// ist ausgeblendet.
|
|
if controller.mode != .tabBar { controller.mode = .tabBar }
|
|
if !controller.isTabBarHidden { controller.isTabBarHidden = true }
|
|
if !controller.sidebar.isHidden { controller.sidebar.isHidden = true }
|
|
}
|
|
|
|
/// Sucht vom eigenen Platz aus nach oben bis zur Wurzel und von dort
|
|
/// nach unten: die Leiste liegt in der SwiftUI-Sicht *über* uns, die
|
|
/// reine Elternkette führt an ihr vorbei.
|
|
private static func tabBarController(from start: UIViewController) -> UITabBarController? {
|
|
var root = start
|
|
while let parent = root.parent { root = parent }
|
|
return search(root)
|
|
}
|
|
|
|
private static func search(_ controller: UIViewController) -> UITabBarController? {
|
|
if let found = controller as? UITabBarController { return found }
|
|
for child in controller.children {
|
|
if let found = search(child) { return found }
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
#endif
|