@sbaiahmed1/react-native-blur 4.0.1 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +155 -47
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/sbaiahmed1/reactnativeblur/BlurType.kt +63 -0
- package/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeBlurPackage.kt +1 -0
- package/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeBlurView.kt +63 -43
- package/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeBlurViewManager.kt +14 -26
- package/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeProgressiveBlurView.kt +320 -0
- package/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeProgressiveBlurViewManager.kt +81 -0
- package/ios/Helpers/BlurStyleHelpers.swift +20 -0
- package/ios/Helpers/ReactNativeProgressiveBlurViewHelper.swift +39 -0
- package/ios/ReactNativeProgressiveBlurView.h +14 -0
- package/ios/ReactNativeProgressiveBlurView.mm +213 -0
- package/ios/ReactNativeProgressiveBlurViewManager.h +4 -0
- package/ios/ReactNativeProgressiveBlurViewManager.mm +137 -0
- package/ios/Views/ProgressiveBlurView.swift +124 -0
- package/ios/Views/VariableBlurView.swift +142 -0
- package/lib/module/BlurView.js +23 -12
- package/lib/module/BlurView.js.map +1 -1
- package/lib/module/LiquidGlassView.js +3 -1
- package/lib/module/LiquidGlassView.js.map +1 -1
- package/lib/module/ProgressiveBlurView.js +98 -0
- package/lib/module/ProgressiveBlurView.js.map +1 -0
- package/lib/module/ReactNativeBlurViewNativeComponent.ts +11 -1
- package/lib/module/ReactNativeProgressiveBlurViewNativeComponent.ts +45 -0
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/BlurView.d.ts.map +1 -1
- package/lib/typescript/src/LiquidGlassView.d.ts.map +1 -1
- package/lib/typescript/src/ProgressiveBlurView.d.ts +97 -0
- package/lib/typescript/src/ProgressiveBlurView.d.ts.map +1 -0
- package/lib/typescript/src/ReactNativeBlurViewNativeComponent.d.ts +1 -1
- package/lib/typescript/src/ReactNativeBlurViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/ReactNativeProgressiveBlurViewNativeComponent.d.ts +14 -0
- package/lib/typescript/src/ReactNativeProgressiveBlurViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/BlurView.tsx +21 -17
- package/src/LiquidGlassView.tsx +3 -4
- package/src/ProgressiveBlurView.tsx +161 -0
- package/src/ReactNativeBlurViewNativeComponent.ts +11 -1
- package/src/ReactNativeProgressiveBlurViewNativeComponent.ts +45 -0
- package/src/index.tsx +6 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
package com.sbaiahmed1.reactnativeblur
|
|
2
2
|
|
|
3
3
|
import com.facebook.react.module.annotations.ReactModule
|
|
4
|
-
import com.facebook.react.uimanager.
|
|
4
|
+
import com.facebook.react.uimanager.ViewGroupManager
|
|
5
5
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
6
6
|
import com.facebook.react.uimanager.ViewManagerDelegate
|
|
7
7
|
import com.facebook.react.uimanager.annotations.ReactProp
|
|
@@ -9,7 +9,7 @@ import com.facebook.react.viewmanagers.ReactNativeBlurViewManagerInterface
|
|
|
9
9
|
import com.facebook.react.viewmanagers.ReactNativeBlurViewManagerDelegate
|
|
10
10
|
|
|
11
11
|
@ReactModule(name = ReactNativeBlurViewManager.NAME)
|
|
12
|
-
class ReactNativeBlurViewManager :
|
|
12
|
+
class ReactNativeBlurViewManager : ViewGroupManager<ReactNativeBlurView>(),
|
|
13
13
|
ReactNativeBlurViewManagerInterface<ReactNativeBlurView> {
|
|
14
14
|
private val mDelegate: ViewManagerDelegate<ReactNativeBlurView>
|
|
15
15
|
|
|
@@ -31,7 +31,7 @@ class ReactNativeBlurViewManager : SimpleViewManager<ReactNativeBlurView>(),
|
|
|
31
31
|
|
|
32
32
|
@ReactProp(name = "blurType")
|
|
33
33
|
override fun setBlurType(view: ReactNativeBlurView?, blurType: String?) {
|
|
34
|
-
view?.setBlurType(blurType ?: "
|
|
34
|
+
view?.setBlurType(blurType ?: "xlight")
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
@ReactProp(name = "blurAmount")
|
|
@@ -44,29 +44,9 @@ class ReactNativeBlurViewManager : SimpleViewManager<ReactNativeBlurView>(),
|
|
|
44
44
|
view?.setReducedTransparencyFallbackColor(reducedTransparencyFallbackColor)
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
@ReactProp(name = "
|
|
48
|
-
fun
|
|
49
|
-
view?.
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
@ReactProp(name = "glassOpacity")
|
|
53
|
-
fun setGlassOpacity(view: ReactNativeBlurView?, glassOpacity: Double) {
|
|
54
|
-
view?.setGlassOpacity(glassOpacity.toFloat())
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
@ReactProp(name = "type")
|
|
58
|
-
fun setType(view: ReactNativeBlurView?, type: String?) {
|
|
59
|
-
view?.setType(type ?: "blur")
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
@ReactProp(name = "glassType")
|
|
63
|
-
fun setGlassType(view: ReactNativeBlurView?, glassType: String?) {
|
|
64
|
-
view?.setGlassType(glassType ?: "clear")
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
@ReactProp(name = "isInteractive")
|
|
68
|
-
fun setIsInteractive(view: ReactNativeBlurView?, isInteractive: Boolean) {
|
|
69
|
-
view?.setIsInteractive(isInteractive)
|
|
47
|
+
@ReactProp(name = "borderRadius")
|
|
48
|
+
override fun setBorderRadius(view: ReactNativeBlurView?, borderRadius: Float) {
|
|
49
|
+
view?.setBorderRadius(borderRadius)
|
|
70
50
|
}
|
|
71
51
|
|
|
72
52
|
@ReactProp(name = "ignoreSafeArea")
|
|
@@ -84,6 +64,14 @@ class ReactNativeBlurViewManager : SimpleViewManager<ReactNativeBlurView>(),
|
|
|
84
64
|
view.cleanup()
|
|
85
65
|
}
|
|
86
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Indicates that React Native's Yoga layout should handle child positioning.
|
|
69
|
+
* Returns false to let React Native manage the layout of children.
|
|
70
|
+
*/
|
|
71
|
+
override fun needsCustomLayoutForChildren(): Boolean {
|
|
72
|
+
return false
|
|
73
|
+
}
|
|
74
|
+
|
|
87
75
|
companion object {
|
|
88
76
|
const val NAME = "ReactNativeBlurView"
|
|
89
77
|
}
|
package/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeProgressiveBlurView.kt
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
package com.sbaiahmed1.reactnativeblur
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.Canvas
|
|
5
|
+
import android.graphics.Color
|
|
6
|
+
import android.graphics.LinearGradient
|
|
7
|
+
import android.graphics.Paint
|
|
8
|
+
import android.graphics.PorterDuff
|
|
9
|
+
import android.graphics.PorterDuffXfermode
|
|
10
|
+
import android.graphics.Shader
|
|
11
|
+
import android.util.AttributeSet
|
|
12
|
+
import android.util.Log
|
|
13
|
+
import android.widget.FrameLayout
|
|
14
|
+
import com.qmdeve.blurview.widget.BlurView
|
|
15
|
+
import androidx.core.graphics.toColorInt
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Android implementation of React Native ProgressiveBlurView component.
|
|
19
|
+
* Uses a combination of normal blur (BlurView) + linear gradient mask to create
|
|
20
|
+
* a progressive blur effect that transitions from blurred to clear.
|
|
21
|
+
*
|
|
22
|
+
* This approach is more reliable than using the library's ProgressiveBlurView,
|
|
23
|
+
* which has limited control over gradient direction and appearance.
|
|
24
|
+
*/
|
|
25
|
+
class ReactNativeProgressiveBlurView : FrameLayout {
|
|
26
|
+
private var blurView: BlurView? = null
|
|
27
|
+
private val gradientPaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
|
28
|
+
|
|
29
|
+
private var currentBlurRadius = DEFAULT_BLUR_RADIUS
|
|
30
|
+
private var currentOverlayColor = Color.TRANSPARENT
|
|
31
|
+
private var currentDirection = "topToBottom"
|
|
32
|
+
private var currentStartOffset = 0.0f
|
|
33
|
+
private var hasExplicitBackground: Boolean = false
|
|
34
|
+
|
|
35
|
+
companion object {
|
|
36
|
+
private const val TAG = "ReactNativeProgressiveBlur"
|
|
37
|
+
private const val MAX_BLUR_RADIUS = 25f
|
|
38
|
+
private const val DEFAULT_BLUR_RADIUS = 10f
|
|
39
|
+
private const val DEBUG = true
|
|
40
|
+
|
|
41
|
+
// Cross-platform blur amount constants
|
|
42
|
+
private const val MIN_BLUR_AMOUNT = 0f
|
|
43
|
+
private const val MAX_BLUR_AMOUNT = 100f
|
|
44
|
+
|
|
45
|
+
private fun logDebug(message: String) {
|
|
46
|
+
if (DEBUG) {
|
|
47
|
+
Log.d(TAG, message)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private fun logWarning(message: String) {
|
|
52
|
+
Log.w(TAG, message)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private fun logError(message: String, throwable: Throwable? = null) {
|
|
56
|
+
Log.e(TAG, message, throwable)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Maps blur amount (0-100) to Android blur radius (0-25).
|
|
61
|
+
*/
|
|
62
|
+
private fun mapBlurAmountToRadius(amount: Float): Float {
|
|
63
|
+
if (amount.isNaN() || amount.isInfinite()) {
|
|
64
|
+
logWarning("Invalid blur amount: $amount, using default")
|
|
65
|
+
return DEFAULT_BLUR_RADIUS
|
|
66
|
+
}
|
|
67
|
+
val clampedAmount = amount.coerceIn(MIN_BLUR_AMOUNT, MAX_BLUR_AMOUNT)
|
|
68
|
+
return (clampedAmount / MAX_BLUR_RADIUS) * MAX_BLUR_RADIUS
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
constructor(context: Context) : super(context) {
|
|
73
|
+
initializeProgressiveBlur()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
|
|
77
|
+
initializeProgressiveBlur()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Initialize the progressive blur view with blur + gradient approach.
|
|
82
|
+
*/
|
|
83
|
+
private fun initializeProgressiveBlur() {
|
|
84
|
+
try {
|
|
85
|
+
// Create and add the blur view as a child
|
|
86
|
+
blurView = BlurView(context, null).apply {
|
|
87
|
+
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
|
88
|
+
setBlurRadius(currentBlurRadius)
|
|
89
|
+
setOverlayColor(currentOverlayColor)
|
|
90
|
+
setBackgroundColor(Color.TRANSPARENT)
|
|
91
|
+
}
|
|
92
|
+
addView(blurView)
|
|
93
|
+
|
|
94
|
+
// Set up the gradient paint
|
|
95
|
+
gradientPaint.style = Paint.Style.FILL
|
|
96
|
+
setWillNotDraw(false) // Enable onDraw for gradient overlay
|
|
97
|
+
|
|
98
|
+
// Set transparent background for the container
|
|
99
|
+
super.setBackgroundColor(Color.TRANSPARENT)
|
|
100
|
+
|
|
101
|
+
logDebug("Initialized progressive blur with blur + gradient approach")
|
|
102
|
+
updateGradient()
|
|
103
|
+
|
|
104
|
+
} catch (e: Exception) {
|
|
105
|
+
logError("Failed to initialize progressive blur view: ${e.message}", e)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
|
110
|
+
super.onSizeChanged(w, h, oldw, oldh)
|
|
111
|
+
if (w > 0 && h > 0) {
|
|
112
|
+
updateGradient()
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Update the gradient shader based on current direction and startOffset.
|
|
118
|
+
*/
|
|
119
|
+
private fun updateGradient() {
|
|
120
|
+
if (width <= 0 || height <= 0) {
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
val (x0, y0, x1, y1) = when (currentDirection) {
|
|
126
|
+
"bottomToTop" -> {
|
|
127
|
+
// Blur at bottom, clear at top
|
|
128
|
+
// point0 (TRANSPARENT/clear) at top, point1 (WHITE/blur) at bottom adjusted by offset
|
|
129
|
+
val offsetPixels = height * currentStartOffset
|
|
130
|
+
floatArrayOf(0f, 0f, 0f, height - offsetPixels)
|
|
131
|
+
}
|
|
132
|
+
"topToBottom" -> {
|
|
133
|
+
// Blur at top, clear at bottom (default)
|
|
134
|
+
// point0 (TRANSPARENT/clear) at bottom, point1 (WHITE/blur) at top adjusted by offset
|
|
135
|
+
val offsetPixels = height * currentStartOffset
|
|
136
|
+
floatArrayOf(0f, height.toFloat(), 0f, offsetPixels)
|
|
137
|
+
}
|
|
138
|
+
"leftToRight" -> {
|
|
139
|
+
val offsetPixels = width * currentStartOffset
|
|
140
|
+
floatArrayOf(offsetPixels, 0f, width.toFloat(), 0f)
|
|
141
|
+
}
|
|
142
|
+
"rightToLeft" -> {
|
|
143
|
+
val offsetPixels = width * currentStartOffset
|
|
144
|
+
floatArrayOf(width.toFloat(), 0f, offsetPixels, 0f)
|
|
145
|
+
}
|
|
146
|
+
else -> floatArrayOf(0f, 0f, 0f, height.toFloat())
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Create gradient: fully transparent -> fully opaque
|
|
150
|
+
// This masks the blur: opaque = blur visible, transparent = blur hidden (clear)
|
|
151
|
+
val gradient = LinearGradient(
|
|
152
|
+
x0, y0, x1, y1,
|
|
153
|
+
intArrayOf(Color.TRANSPARENT, Color.WHITE),
|
|
154
|
+
floatArrayOf(0f, 1f),
|
|
155
|
+
Shader.TileMode.CLAMP
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
gradientPaint.shader = gradient
|
|
159
|
+
|
|
160
|
+
logDebug("Updated gradient: direction=$currentDirection, start=($x0,$y0), end=($x1,$y1), offset=$currentStartOffset")
|
|
161
|
+
invalidate()
|
|
162
|
+
|
|
163
|
+
} catch (e: Exception) {
|
|
164
|
+
logError("Failed to update gradient: ${e.message}", e)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
override fun dispatchDraw(canvas: Canvas) {
|
|
169
|
+
if (width <= 0 || height <= 0) {
|
|
170
|
+
super.dispatchDraw(canvas)
|
|
171
|
+
return
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Use a layer to apply the gradient mask
|
|
175
|
+
val saveCount = canvas.saveLayer(0f, 0f, width.toFloat(), height.toFloat(), null)
|
|
176
|
+
|
|
177
|
+
// Draw the blur view
|
|
178
|
+
super.dispatchDraw(canvas)
|
|
179
|
+
|
|
180
|
+
// Apply gradient mask using DST_IN to make the blur gradually transparent
|
|
181
|
+
gradientPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
|
|
182
|
+
canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), gradientPaint)
|
|
183
|
+
gradientPaint.xfermode = null
|
|
184
|
+
|
|
185
|
+
canvas.restoreToCount(saveCount)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Override setBackgroundColor to handle background preservation.
|
|
190
|
+
*/
|
|
191
|
+
override fun setBackgroundColor(color: Int) {
|
|
192
|
+
logDebug("setBackgroundColor called: $color")
|
|
193
|
+
|
|
194
|
+
if (color != Color.TRANSPARENT) {
|
|
195
|
+
hasExplicitBackground = true
|
|
196
|
+
logDebug("Stored explicit background color: $color")
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (hasExplicitBackground && color != Color.TRANSPARENT) {
|
|
200
|
+
logDebug("Applying background color: $color")
|
|
201
|
+
super.setBackgroundColor(color)
|
|
202
|
+
} else {
|
|
203
|
+
logDebug("Keeping transparent background for blur effect")
|
|
204
|
+
super.setBackgroundColor(Color.TRANSPARENT)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Called when the view is detached from a window.
|
|
210
|
+
*/
|
|
211
|
+
override fun onDetachedFromWindow() {
|
|
212
|
+
super.onDetachedFromWindow()
|
|
213
|
+
cleanup()
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Cleanup method to prevent memory leaks.
|
|
218
|
+
*/
|
|
219
|
+
fun cleanup() {
|
|
220
|
+
hasExplicitBackground = false
|
|
221
|
+
removeCallbacks(null)
|
|
222
|
+
blurView = null
|
|
223
|
+
logDebug("View cleaned up")
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Set the blur amount with cross-platform mapping.
|
|
228
|
+
* @param amount The blur amount value (0-100), will be mapped to Android's 0-25 radius range
|
|
229
|
+
*/
|
|
230
|
+
fun setBlurAmount(amount: Float) {
|
|
231
|
+
currentBlurRadius = mapBlurAmountToRadius(amount)
|
|
232
|
+
logDebug("setBlurAmount: $amount -> $currentBlurRadius")
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
blurView?.setBlurRadius(currentBlurRadius)
|
|
236
|
+
invalidate()
|
|
237
|
+
} catch (e: Exception) {
|
|
238
|
+
logError("Failed to set blur radius: ${e.message}", e)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Set the direction of the progressive blur gradient.
|
|
244
|
+
* @param direction The direction string: "blurredTopClearBottom" or "blurredBottomClearTop"
|
|
245
|
+
*/
|
|
246
|
+
fun setDirection(direction: String) {
|
|
247
|
+
currentDirection = when (direction.lowercase()) {
|
|
248
|
+
"blurredbottomcleartop", "bottomtotop", "bottom" -> "bottomToTop"
|
|
249
|
+
"blurredtopclearbottom", "toptobottom", "top" -> "topToBottom"
|
|
250
|
+
"blurredlefttoclearright", "lefttoright", "left" -> "leftToRight"
|
|
251
|
+
"blurredrightoclearleft", "righttoleft", "right" -> "rightToLeft"
|
|
252
|
+
else -> {
|
|
253
|
+
logWarning("Unknown direction: $direction, defaulting to topToBottom")
|
|
254
|
+
"topToBottom"
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
logDebug("setDirection: $direction -> $currentDirection")
|
|
258
|
+
|
|
259
|
+
try {
|
|
260
|
+
updateGradient()
|
|
261
|
+
} catch (e: Exception) {
|
|
262
|
+
logError("Failed to set gradient direction: ${e.message}", e)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Set the start offset for the progressive blur.
|
|
268
|
+
* Controls where the gradient transition begins.
|
|
269
|
+
*
|
|
270
|
+
* @param offset The offset value (0.0 to 1.0) - where 0 starts immediately, 1 delays to the end
|
|
271
|
+
*/
|
|
272
|
+
fun setStartOffset(offset: Float) {
|
|
273
|
+
currentStartOffset = offset.coerceIn(0.0f, 1.0f)
|
|
274
|
+
logDebug("setStartOffset: $offset -> clamped to $currentStartOffset")
|
|
275
|
+
|
|
276
|
+
try {
|
|
277
|
+
updateGradient()
|
|
278
|
+
} catch (e: Exception) {
|
|
279
|
+
logError("Failed to update startOffset: ${e.message}", e)
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Set the blur type which determines the overlay color.
|
|
285
|
+
* @param type The blur type string (case-insensitive)
|
|
286
|
+
*/
|
|
287
|
+
fun setBlurType(type: String) {
|
|
288
|
+
val blurType = BlurType.fromString(type)
|
|
289
|
+
currentOverlayColor = blurType.overlayColor
|
|
290
|
+
logDebug("setBlurType: $type -> ${blurType.name} -> ${Integer.toHexString(currentOverlayColor)}")
|
|
291
|
+
|
|
292
|
+
try {
|
|
293
|
+
blurView?.setOverlayColor(currentOverlayColor)
|
|
294
|
+
invalidate()
|
|
295
|
+
} catch (e: Exception) {
|
|
296
|
+
logError("Failed to set overlay color: ${e.message}", e)
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Set the fallback color for reduced transparency accessibility mode.
|
|
302
|
+
* @param color The color string in hex format (e.g., "#FF0000") or null to clear
|
|
303
|
+
*/
|
|
304
|
+
fun setReducedTransparencyFallbackColor(color: String?) {
|
|
305
|
+
if (color.isNullOrBlank()) {
|
|
306
|
+
logDebug("Cleared reduced transparency fallback color")
|
|
307
|
+
return
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
val fallbackColor = color.toColorInt()
|
|
312
|
+
logDebug("setReducedTransparencyFallbackColor: $color -> ${Integer.toHexString(fallbackColor)}")
|
|
313
|
+
// Android doesn't have a direct equivalent to iOS's "Reduce Transparency" setting
|
|
314
|
+
} catch (e: IllegalArgumentException) {
|
|
315
|
+
logWarning("Invalid color format for reduced transparency fallback: $color - ${e.message}")
|
|
316
|
+
} catch (e: Exception) {
|
|
317
|
+
logError("Error parsing reduced transparency fallback color: $color", e)
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
package com.sbaiahmed1.reactnativeblur
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
4
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
5
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManagerDelegate
|
|
7
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
8
|
+
import com.facebook.react.viewmanagers.ReactNativeProgressiveBlurViewManagerInterface
|
|
9
|
+
import com.facebook.react.viewmanagers.ReactNativeProgressiveBlurViewManagerDelegate
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* View manager for the ReactNativeProgressiveBlurView component.
|
|
13
|
+
* Handles prop updates and view lifecycle for progressive blur effects on Android.
|
|
14
|
+
*/
|
|
15
|
+
@ReactModule(name = ReactNativeProgressiveBlurViewManager.NAME)
|
|
16
|
+
class ReactNativeProgressiveBlurViewManager : SimpleViewManager<ReactNativeProgressiveBlurView>(),
|
|
17
|
+
ReactNativeProgressiveBlurViewManagerInterface<ReactNativeProgressiveBlurView> {
|
|
18
|
+
private val mDelegate: ViewManagerDelegate<ReactNativeProgressiveBlurView>
|
|
19
|
+
|
|
20
|
+
init {
|
|
21
|
+
mDelegate = ReactNativeProgressiveBlurViewManagerDelegate(this)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
override fun getDelegate(): ViewManagerDelegate<ReactNativeProgressiveBlurView>? {
|
|
25
|
+
return mDelegate
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
override fun getName(): String {
|
|
29
|
+
return NAME
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public override fun createViewInstance(context: ThemedReactContext): ReactNativeProgressiveBlurView {
|
|
33
|
+
return ReactNativeProgressiveBlurView(context)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@ReactProp(name = "blurType")
|
|
37
|
+
override fun setBlurType(view: ReactNativeProgressiveBlurView?, blurType: String?) {
|
|
38
|
+
// Provide default value if blurType is null or empty
|
|
39
|
+
val safeBlurType = if (blurType.isNullOrBlank()) "regular" else blurType
|
|
40
|
+
view?.setBlurType(safeBlurType)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@ReactProp(name = "blurAmount")
|
|
44
|
+
override fun setBlurAmount(view: ReactNativeProgressiveBlurView?, blurAmount: Double) {
|
|
45
|
+
view?.setBlurAmount(blurAmount.toFloat())
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@ReactProp(name = "direction")
|
|
49
|
+
override fun setDirection(view: ReactNativeProgressiveBlurView?, direction: String?) {
|
|
50
|
+
// Provide default value if direction is null or empty
|
|
51
|
+
val safeDirection = if (direction.isNullOrBlank()) "blurredTopClearBottom" else direction
|
|
52
|
+
view?.setDirection(safeDirection)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@ReactProp(name = "startOffset")
|
|
56
|
+
override fun setStartOffset(view: ReactNativeProgressiveBlurView?, startOffset: Double) {
|
|
57
|
+
view?.setStartOffset(startOffset.toFloat())
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@ReactProp(name = "reducedTransparencyFallbackColor")
|
|
61
|
+
override fun setReducedTransparencyFallbackColor(
|
|
62
|
+
view: ReactNativeProgressiveBlurView?,
|
|
63
|
+
reducedTransparencyFallbackColor: String?
|
|
64
|
+
) {
|
|
65
|
+
view?.setReducedTransparencyFallbackColor(reducedTransparencyFallbackColor)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Called when view is detached from view hierarchy and allows for cleanup.
|
|
70
|
+
* This prevents the white screen issue during navigation transitions on Android.
|
|
71
|
+
*/
|
|
72
|
+
override fun onDropViewInstance(view: ReactNativeProgressiveBlurView) {
|
|
73
|
+
super.onDropViewInstance(view)
|
|
74
|
+
// Call cleanup to reset state and prevent white screen artifacts
|
|
75
|
+
view.cleanup()
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
companion object {
|
|
79
|
+
const val NAME = "ReactNativeProgressiveBlurView"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -30,6 +30,26 @@ func blurStyleFromString(_ styleString: String) -> UIBlurEffect.Style {
|
|
|
30
30
|
return .systemThickMaterial
|
|
31
31
|
case "systemChromeMaterial":
|
|
32
32
|
return .systemChromeMaterial
|
|
33
|
+
case "systemUltraThinMaterialLight":
|
|
34
|
+
return .systemUltraThinMaterialLight
|
|
35
|
+
case "systemThinMaterialLight":
|
|
36
|
+
return .systemThinMaterialLight
|
|
37
|
+
case "systemMaterialLight":
|
|
38
|
+
return .systemMaterialLight
|
|
39
|
+
case "systemThickMaterialLight":
|
|
40
|
+
return .systemThickMaterialLight
|
|
41
|
+
case "systemChromeMaterialLight":
|
|
42
|
+
return .systemChromeMaterialLight
|
|
43
|
+
case "systemUltraThinMaterialDark":
|
|
44
|
+
return .systemUltraThinMaterialDark
|
|
45
|
+
case "systemThinMaterialDark":
|
|
46
|
+
return .systemThinMaterialDark
|
|
47
|
+
case "systemMaterialDark":
|
|
48
|
+
return .systemMaterialDark
|
|
49
|
+
case "systemThickMaterialDark":
|
|
50
|
+
return .systemThickMaterialDark
|
|
51
|
+
case "systemChromeMaterialDark":
|
|
52
|
+
return .systemChromeMaterialDark
|
|
33
53
|
default:
|
|
34
54
|
return .extraLight
|
|
35
55
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// ReactNativeProgressiveBlurViewHelper.swift
|
|
2
|
+
|
|
3
|
+
import SwiftUI
|
|
4
|
+
import UIKit
|
|
5
|
+
|
|
6
|
+
// MARK: - Objective-C Bridging Helpers for Progressive Blur
|
|
7
|
+
|
|
8
|
+
@objc public class ReactNativeProgressiveBlurViewHelper: NSObject {
|
|
9
|
+
|
|
10
|
+
/// Creates and returns a progressive blur view.
|
|
11
|
+
@objc public static func createProgressiveBlurViewWithFrame(_ frame: CGRect) -> ProgressiveBlurView {
|
|
12
|
+
return ProgressiveBlurView(frame: frame)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/// Updates the progressive blur view with a new blur amount.
|
|
16
|
+
@objc public static func updateProgressiveBlurView(_ blurView: ProgressiveBlurView, withBlurAmount blurAmount: Double) {
|
|
17
|
+
blurView.blurAmount = blurAmount
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/// Updates the progressive blur view with a new direction.
|
|
21
|
+
@objc public static func updateProgressiveBlurView(_ blurView: ProgressiveBlurView, withDirection direction: String) {
|
|
22
|
+
blurView.direction = direction
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/// Updates the progressive blur view with a new start offset.
|
|
26
|
+
@objc public static func updateProgressiveBlurView(_ blurView: ProgressiveBlurView, withStartOffset startOffset: Double) {
|
|
27
|
+
blurView.startOffset = startOffset
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/// Updates the progressive blur view with a new blur type.
|
|
31
|
+
@objc public static func updateProgressiveBlurView(_ blurView: ProgressiveBlurView, withBlurType blurType: String) {
|
|
32
|
+
blurView.blurTypeString = blurType
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// Updates the progressive blur view with a new reduced transparency fallback color.
|
|
36
|
+
@objc public static func updateProgressiveBlurView(_ blurView: ProgressiveBlurView, withReducedTransparencyFallbackColor reducedTransparencyFallbackColor: UIColor) {
|
|
37
|
+
blurView.reducedTransparencyFallbackColor = reducedTransparencyFallbackColor
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#import <React/RCTViewComponentView.h>
|
|
2
|
+
#import <UIKit/UIKit.h>
|
|
3
|
+
|
|
4
|
+
#ifndef NativeComponentExampleComponentView_h
|
|
5
|
+
#define NativeComponentExampleComponentView_h
|
|
6
|
+
|
|
7
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
8
|
+
|
|
9
|
+
@interface ReactNativeProgressiveBlurView : RCTViewComponentView
|
|
10
|
+
@end
|
|
11
|
+
|
|
12
|
+
NS_ASSUME_NONNULL_END
|
|
13
|
+
|
|
14
|
+
#endif /* NativeComponentExampleComponentView_h */
|