Fix #36: Tab-Bar-Flicker durch UIKit/SwiftUI-Konflikt behoben

- SwiftUI .toolbarBackground/.toolbarColorScheme-Modifier für .tabBar
  aus ContentView entfernt – Konflikt mit UITabBar.appearance() beseitigt
- applyTabBarAppearance in statische Methode umgewandelt
- applyInitialTabBarAppearance() in AppDelegate.didFinishLaunchingWithOptions
  aufgerufen – setzt UIKit-Appearance VOR der View-Erstellung
- configureWithTransparentBackground → configureWithOpaqueBackground:
  verhindert weißes Bleed-through bei dunklen Themes
- Alpha-Komponente aus Tab-Bar-Hintergrundfarbe entfernt (vollständig opak)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-23 13:56:49 +02:00
parent 8af0309580
commit 8180fcbcbc
2 changed files with 22 additions and 14 deletions
-5
View File
@@ -52,11 +52,6 @@ struct ContentView: View {
.tabItem { Label("Einstellungen", systemImage: "gearshape") } .tabItem { Label("Einstellungen", systemImage: "gearshape") }
.tag(3) .tag(3)
} }
// Tab-Bar-Styling einmalig auf TabView statt auf jedem Tab setzen
// verhindert weißes Aufblitzen beim Tab-Wechsel (Issue #36)
.toolbarBackground(theme.backgroundPrimary.opacity(0.92), for: .tabBar)
.toolbarBackground(.visible, for: .tabBar)
.toolbarColorScheme(theme.id.isDark ? .dark : .light, for: .tabBar)
.fullScreenCover(isPresented: $showingNahbarOnboarding) { .fullScreenCover(isPresented: $showingNahbarOnboarding) {
OnboardingContainerView { OnboardingContainerView {
nahbarOnboardingDone = true nahbarOnboardingDone = true
+22 -9
View File
@@ -16,6 +16,8 @@ final class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCent
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool { ) -> Bool {
UNUserNotificationCenter.current().delegate = self UNUserNotificationCenter.current().delegate = self
// UIKit-Appearance VOR der View-Erstellung setzen verhindert weißes Aufblitzen
NahbarApp.applyInitialTabBarAppearance()
return true return true
} }
@@ -103,13 +105,13 @@ struct NahbarApp: App {
.environment(\.nahbarTheme, activeTheme) .environment(\.nahbarTheme, activeTheme)
.tint(activeTheme.accent) .tint(activeTheme.accent)
.onAppear { .onAppear {
applyTabBarAppearance(activeTheme) NahbarApp.applyTabBarAppearance(activeTheme)
cloudSyncMonitor.startMonitoring(iCloudEnabled: icloudSyncEnabled) cloudSyncMonitor.startMonitoring(iCloudEnabled: icloudSyncEnabled)
AftermathNotificationManager.shared.registerCategory() AftermathNotificationManager.shared.registerCategory()
logger.info("App gestartet. Container-Modus: \(String(describing: NahbarApp.containerFallback))") logger.info("App gestartet. Container-Modus: \(String(describing: NahbarApp.containerFallback))")
AppEventLog.shared.record("Container-Modus: \(NahbarApp.containerFallback)", level: .info, category: "Lifecycle") AppEventLog.shared.record("Container-Modus: \(NahbarApp.containerFallback)", level: .info, category: "Lifecycle")
} }
.onChange(of: activeThemeIDRaw) { _, _ in applyTabBarAppearance(activeTheme) } .onChange(of: activeThemeIDRaw) { _, _ in NahbarApp.applyTabBarAppearance(activeTheme) }
.onChange(of: icloudSyncEnabled) { _, enabled in .onChange(of: icloudSyncEnabled) { _, enabled in
cloudSyncMonitor.startMonitoring(iCloudEnabled: enabled) cloudSyncMonitor.startMonitoring(iCloudEnabled: enabled)
} }
@@ -122,11 +124,22 @@ struct NahbarApp: App {
} }
} }
private func applyTabBarAppearance(_ theme: NahbarTheme) { /// Liest das aktive Theme aus UserDefaults und setzt UITabBar-Appearance
let bg = UIColor(theme.backgroundPrimary).withAlphaComponent(0.88) /// vor der ersten View-Erstellung (AppDelegate-Kontext).
static func applyInitialTabBarAppearance() {
let themeID = UserDefaults.standard.string(forKey: "activeThemeID")
.flatMap { ThemeID(rawValue: $0) } ?? .linen
applyTabBarAppearance(NahbarTheme.theme(for: themeID))
}
/// Setzt UITabBar- und UINavigationBar-Appearance für das gegebene Theme.
/// Statisch, damit AppDelegate und Theme-Change-Handler dieselbe Logik nutzen.
/// configureWithOpaqueBackground() verhindert das weiße Aufblitzen bei dunklen Themes.
static func applyTabBarAppearance(_ theme: NahbarTheme) {
let bg = UIColor(theme.backgroundPrimary) // vollständig opak kein Bleed-through
let normal = UIColor(theme.contentTertiary) let normal = UIColor(theme.contentTertiary)
let selected = UIColor(theme.accent) let selected = UIColor(theme.accent)
let border = UIColor(theme.borderSubtle).withAlphaComponent(0.6) let border = UIColor(theme.borderSubtle)
let item = UITabBarItemAppearance() let item = UITabBarItemAppearance()
item.normal.iconColor = normal item.normal.iconColor = normal
@@ -135,7 +148,7 @@ struct NahbarApp: App {
item.selected.titleTextAttributes = [.foregroundColor: selected] item.selected.titleTextAttributes = [.foregroundColor: selected]
let tabAppearance = UITabBarAppearance() let tabAppearance = UITabBarAppearance()
tabAppearance.configureWithTransparentBackground() tabAppearance.configureWithOpaqueBackground() // statt transparent stabil bei dunklen Themes
tabAppearance.backgroundColor = bg tabAppearance.backgroundColor = bg
tabAppearance.shadowColor = border tabAppearance.shadowColor = border
tabAppearance.stackedLayoutAppearance = item tabAppearance.stackedLayoutAppearance = item
@@ -145,11 +158,11 @@ struct NahbarApp: App {
UITabBar.appearance().standardAppearance = tabAppearance UITabBar.appearance().standardAppearance = tabAppearance
UITabBar.appearance().scrollEdgeAppearance = tabAppearance UITabBar.appearance().scrollEdgeAppearance = tabAppearance
let navBg = UIColor(theme.backgroundPrimary).withAlphaComponent(0.92) let navBg = UIColor(theme.backgroundPrimary)
let titleColor = UIColor(theme.contentPrimary) let titleColor = UIColor(theme.contentPrimary)
let navAppearance = UINavigationBarAppearance() let navAppearance = UINavigationBarAppearance()
navAppearance.configureWithTransparentBackground() navAppearance.configureWithOpaqueBackground()
navAppearance.backgroundColor = navBg navAppearance.backgroundColor = navBg
navAppearance.shadowColor = border navAppearance.shadowColor = border
navAppearance.titleTextAttributes = [.foregroundColor: titleColor] navAppearance.titleTextAttributes = [.foregroundColor: titleColor]