diff --git a/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeBlurView.kt b/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeBlurView.kt index c8c2998..de996c8 100644 --- a/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeBlurView.kt +++ b/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeBlurView.kt @@ -107,15 +107,12 @@ class ReactNativeBlurView : BlurViewGroup { if (isBlurInitialized) return - // Defer the blur root swap to next frame so the view tree is fully mounted - val runnable = Runnable { - initRunnable = null - if (isBlurInitialized) return@Runnable - swapBlurRootToScreenAncestor() - initializeBlur() - } - initRunnable = runnable - post(runnable) + // Immediately try to swap blur root and initialize. + // We avoid posting a runnable to prevent the 1-second delay artifact. + // If the parent hierarchy is not ready yet (unlikely in onAttachedToWindow), + // we could fall back to post, but for now we prioritize immediate execution. + swapBlurRootToScreenAncestor() + initializeBlur() } /** diff --git a/example/app.json b/example/app.json index f71dd7a..ecb20c2 100644 --- a/example/app.json +++ b/example/app.json @@ -8,7 +8,8 @@ "scheme": "exampleapp", "userInterfaceStyle": "automatic", "ios": { - "icon": "./assets/expo.icon" + "icon": "./assets/expo.icon", + "bundleIdentifier": "com.sbaiahmed1.reactnativeblurexampleapp" }, "android": { "adaptiveIcon": { diff --git a/example/package.json b/example/package.json index bdee0b0..cf81b1a 100644 --- a/example/package.json +++ b/example/package.json @@ -6,6 +6,7 @@ "scripts": { "start": "expo start", "android": "expo run:android", + "prebuild:ios": "expo prebuild --platform ios --clean", "ios": "expo run:ios", "web": "expo start --web", "lint": "expo lint", @@ -47,4 +48,4 @@ "react-native-monorepo-config": "*", "typescript": "~5.9.2" } -} +} \ No newline at end of file diff --git a/ios/Views/AdvancedBlurView.swift b/ios/Views/AdvancedBlurView.swift index e1331c8..5e080af 100644 --- a/ios/Views/AdvancedBlurView.swift +++ b/ios/Views/AdvancedBlurView.swift @@ -68,7 +68,14 @@ import UIKit hosting.view.backgroundColor = .clear hosting.view.translatesAutoresizingMaskIntoConstraints = false - addSubview(hosting.view) + // Insert at index 0 to ensure it stays behind any potential subviews (though usually this view has no children) + // This fixes the z-ordering bug where blur covers content + if !subviews.isEmpty { + insertSubview(hosting.view, at: 0) + } else { + addSubview(hosting.view) + } + NSLayoutConstraint.activate([ hosting.view.topAnchor.constraint(equalTo: topAnchor), hosting.view.leadingAnchor.constraint(equalTo: leadingAnchor), @@ -80,8 +87,20 @@ import UIKit } private func updateView() { - if hostingController != nil { - setupHostingController() + if let hosting = hostingController { + // Update the existing controller's root view to avoid expensive recreation + // This fixes performance bottlenecks and state synchronization issues + let blurStyle = blurStyleFromString(blurTypeString) + let swiftUIView = BasicColoredView( + blurAmount: blurAmount, + blurStyle: blurStyle, + ignoreSafeArea: ignoreSafeArea, + reducedTransparencyFallbackColor: reducedTransparencyFallbackColor + ) + hosting.rootView = swiftUIView + hosting.view.setNeedsLayout() + } else { + setupHostingController() } } diff --git a/ios/Views/VibrancyEffectView.swift b/ios/Views/VibrancyEffectView.swift index 481b686..82cd72d 100644 --- a/ios/Views/VibrancyEffectView.swift +++ b/ios/Views/VibrancyEffectView.swift @@ -68,16 +68,24 @@ import UIKit let blurEffect = UIBlurEffect(style: style) let vibrancyEffect = UIVibrancyEffect(blurEffect: blurEffect) - // Use animator to control blur intensity - blurAnimator = UIViewPropertyAnimator(duration: 1, curve: .linear) - blurAnimator?.addAnimations { [weak self] in - self?.blurEffectView.effect = blurEffect - self?.vibrancyEffectView.effect = vibrancyEffect + // Set effects directly first to ensure they are visible + // Animating them from nil often causes issues with UIVibrancyEffect + blurEffectView.effect = blurEffect + vibrancyEffectView.effect = vibrancyEffect + + // Create animator to adjust intensity + blurAnimator = UIViewPropertyAnimator(duration: 1, curve: .linear) { [weak self] in + self?.blurEffectView.effect = nil + self?.vibrancyEffectView.effect = nil } // Convert blurAmount (0-100) to intensity (0.0-1.0) + // We reverse the logic: + // fractionComplete = 0.0 -> effects are fully applied (start state) + // fractionComplete = 1.0 -> effects are removed (end state) + // So to get desired intensity X, we set fractionComplete to (1 - X) let intensity = min(max(blurAmount / 100.0, 0.0), 1.0) - blurAnimator?.fractionComplete = intensity + blurAnimator?.fractionComplete = 1.0 - intensity // Stop the animation at the current state DispatchQueue.main.async { [weak self, weak blurAnimator] in