Die Ränder kommen jetzt von der Stelle, die sie kennt
Mein voriger Versuch war an der Quelle falsch, nicht an der Rechnung. **Was ich gebaut hatte:** die Sicherheitsränder in `RootView` messen und über die Umgebung an den Player reichen. Gemessen in einer Ansicht, angewendet in einer anderen, über eine Drehung hinweg — drei Gelegenheiten, daneben zu liegen. Im Simulator ging es gut, auf dem Gerät nicht: dort standen im Querformat links 75 und rechts 28 Punkt Rand, und der Untertitel wurde von der Bildschirmkante abgeschnitten. **Warum SwiftUI hier nicht hilft.** Der Sicherheitsrand ist dort kein Wert, den man erfragt, sondern einer, den man verbraucht: wer ihn respektiert, sieht null, und wer ihn mit `ignoresSafeArea` überschreitet, sieht danach ebenfalls null. Beide Auswege habe ich durchgespielt und beide gemessen. Nimmt man der Ansicht das `ignoresSafeArea`, sitzen die Knöpfe richtig — aber die Bildfläche verliert es mit, und das Bild ist im Querformat um die Notch-Breite schmaler. Schiebt man einen `GeometryReader` dazwischen, passiert dasselbe. **Das Fenster weiß es immer**, in der richtigen Ausrichtung und in dem Moment, in dem gefragt wird. `ScreenSafeArea` ist die eine Stelle in dieser App, die so fragt, und die eine, an der es keinen SwiftUI-Weg gibt. Nachgeholt wird der Wert bei jeder Änderung der Fläche — das ist genau der Moment des Drehens. Nachgemessen im Simulator gegen die Jellyfin-Attrappe: im Querformat meldet das Fenster 0/62/62/20, und damit stehen Kopfzeile, Schieberegler und Zeitangaben vollständig im sichtbaren Bereich, während das Bild bis an die Kanten reicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6326c8c24c
commit
22f824b000
@@ -73,11 +73,6 @@ struct RootView: View {
|
||||
/// Bereichs, der den Sicherheitsrand gleich darauf ignoriert — innerhalb
|
||||
/// wäre er längst null.
|
||||
@State private var statusBarHeight: CGFloat = 0
|
||||
/// Die vollen Sicherheitsränder des Bildschirms.
|
||||
///
|
||||
/// Hier gemessen und nicht im Player: der bekommt `ignoresSafeArea()` und
|
||||
/// sieht danach überall null. Siehe `flixyScreenInsets`.
|
||||
@State private var screenInsets = EdgeInsets()
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
@@ -121,12 +116,9 @@ struct RootView: View {
|
||||
// Hier und nicht weiter innen: ab dem `HStack` wird der obere
|
||||
// Sicherheitsrand ignoriert, damit der Inhalt bis an den
|
||||
// Bildschirmrand reicht. Wer danach misst, bekommt null.
|
||||
.onGeometryChange(for: EdgeInsets.self) { proxy in
|
||||
proxy.safeAreaInsets
|
||||
} action: { neue in
|
||||
screenInsets = neue
|
||||
statusBarHeight = neue.top
|
||||
}
|
||||
.onGeometryChange(for: CGFloat.self) { proxy in
|
||||
proxy.safeAreaInsets.top
|
||||
} action: { statusBarHeight = $0 }
|
||||
// Hier statt in der Scene: eine View wertet Beobachtungsänderungen
|
||||
// zuverlässig neu aus, ein Scene-Body nicht.
|
||||
.flixyAccent(theme)
|
||||
@@ -152,6 +144,12 @@ struct RootView: View {
|
||||
// ist, und der Übergang ist ruhig.
|
||||
.overlay {
|
||||
if playback.presentation == .full, let player {
|
||||
// **Bildfüllend, und der Player passt drinnen selbst auf.**
|
||||
//
|
||||
// Ohne diese Zeile verliert die Bildfläche ihr
|
||||
// `ignoresSafeArea` mit — das Bild wäre im Querformat um die
|
||||
// Notch-Breite schmaler. Wo der Schirm aufhört, holt sich der
|
||||
// Player deshalb aus dem Fenster; siehe `ScreenSafeArea`.
|
||||
PlayerView(model: player)
|
||||
.ignoresSafeArea()
|
||||
.transition(.move(edge: .bottom))
|
||||
@@ -167,10 +165,6 @@ struct RootView: View {
|
||||
// bleiben, die es auf dem neuen Server gar nicht gibt.
|
||||
if newPhase == .ready, case .library = selection { selection = .home }
|
||||
}
|
||||
// **Ganz am Ende der Kette.** Die Umgebung fliesst von aussen nach
|
||||
// innen: stünde die Zeile vor `.overlay`, umschlösse das Overlay sie
|
||||
// und der Player bekäme den Wert nicht. Hier umschliesst sie beides.
|
||||
.flixyScreenInsets(screenInsets)
|
||||
.onChange(of: sizeClass) { _, _ in
|
||||
// Beim Drehen oder Teilen des Fensters wechselt die Form der
|
||||
// Navigation — und mit ihr, welche Ziele es überhaupt gibt. Eine
|
||||
|
||||
Reference in New Issue
Block a user