react-native-controlled-input 0.19.0 → 0.20.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.
|
@@ -5,7 +5,6 @@ import android.util.AttributeSet
|
|
|
5
5
|
import android.util.Log
|
|
6
6
|
import android.util.TypedValue
|
|
7
7
|
import android.view.View
|
|
8
|
-
import android.view.ViewTreeObserver
|
|
9
8
|
import android.view.inputmethod.InputMethodManager
|
|
10
9
|
import android.widget.EditText
|
|
11
10
|
import android.widget.LinearLayout
|
|
@@ -68,114 +67,28 @@ class ControlledInputView : LinearLayout, LifecycleOwner {
|
|
|
68
67
|
private var windowLifecycleBound = false
|
|
69
68
|
|
|
70
69
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
70
|
+
* Hidden [EditText] used only as KBC's [FocusedInputObserver.lastFocusedInput]: [syncUpLayout]
|
|
71
|
+
* reads [EditText]-scoped geometry. It is NOT focused and does not participate in the focus
|
|
72
|
+
* chain — we push state via reflection + synthetic selection events instead.
|
|
74
73
|
*/
|
|
75
|
-
private
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
* Layout height is 0 so LinearLayout ignores it visually. onLayout() forces its bounds to
|
|
86
|
-
* match ControlledInputView so keyboard-controller reads the correct width/height/position.
|
|
87
|
-
*/
|
|
88
|
-
private val focusProxy: EditText by lazy {
|
|
89
|
-
EditText(context).also { proxy ->
|
|
90
|
-
proxy.layoutParams = LayoutParams(0, 0)
|
|
91
|
-
// Must stay VISIBLE — Android's canTakeFocus() returns false for INVISIBLE/GONE views,
|
|
92
|
-
// causing requestFocus() to silently fail. Use alpha=0 to hide it visually instead.
|
|
93
|
-
proxy.alpha = 0f
|
|
94
|
-
proxy.isFocusableInTouchMode = true
|
|
95
|
-
proxy.showSoftInputOnFocus = false
|
|
96
|
-
proxy.isClickable = false
|
|
97
|
-
proxy.isCursorVisible = false
|
|
98
|
-
proxy.isLongClickable = false
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
private fun requestFocusProxy() {
|
|
103
|
-
val fontSize = viewModel.inputStyle.value?.fontSize?.toFloat()
|
|
104
|
-
Log.d(TAG, "──── requestFocusProxy ────")
|
|
105
|
-
Log.d(TAG, " fontSize=$fontSize")
|
|
106
|
-
Log.d(TAG, " proxy before: isFocused=${focusProxy.isFocused} size=${focusProxy.width}x${focusProxy.height}")
|
|
107
|
-
|
|
108
|
-
// Sync proxy ID with ControlledInputView's React Native tag BEFORE requestFocus(),
|
|
109
|
-
// so KeyboardAnimationCallback.focusListener sets viewTagFocused = this.id (not -1).
|
|
110
|
-
// Without this, KeyboardAwareScrollView JS sees e.target=-1 → focusWasChanged=false
|
|
111
|
-
// → layout.value never updated → maybeScroll() always returns 0 → no scroll.
|
|
112
|
-
focusProxy.id = this.id
|
|
113
|
-
Log.d(TAG, " proxy.id set to ${focusProxy.id} (= ControlledInputView RN tag)")
|
|
114
|
-
|
|
115
|
-
// Sync textSize so KeyboardControllerSelectionWatcher computes the correct
|
|
116
|
-
// cursor Y via android.text.Layout.getLineBottom() — used as `customHeight`
|
|
117
|
-
// in KeyboardAwareScrollView to determine how far to scroll.
|
|
118
|
-
fontSize?.let {
|
|
119
|
-
focusProxy.setTextSize(TypedValue.COMPLEX_UNIT_SP, it)
|
|
120
|
-
Log.d(TAG, " proxy textSize set to ${focusProxy.textSize}px (${it}sp)")
|
|
74
|
+
private val kbcLayoutHost: EditText by lazy {
|
|
75
|
+
EditText(context).also { v ->
|
|
76
|
+
v.layoutParams = LayoutParams(0, 0)
|
|
77
|
+
v.alpha = 0f
|
|
78
|
+
v.isFocusable = false
|
|
79
|
+
v.isFocusableInTouchMode = false
|
|
80
|
+
v.showSoftInputOnFocus = false
|
|
81
|
+
v.isClickable = false
|
|
82
|
+
v.isCursorVisible = false
|
|
83
|
+
v.isLongClickable = false
|
|
121
84
|
}
|
|
122
|
-
|
|
123
|
-
focusProxy.requestFocus()
|
|
124
|
-
Log.d(TAG, " proxy after requestFocus: isFocused=${focusProxy.isFocused} hasFocus=${focusProxy.hasFocus()}")
|
|
125
|
-
|
|
126
|
-
if (focusProxy.isFocused) {
|
|
127
|
-
// Proxy stole Android focus from AndroidComposeView → Compose will fire onBlur.
|
|
128
|
-
// Mark restoration mode so onBlur knows to recover (not dispatch BlurEvent to JS).
|
|
129
|
-
isRestoringComposeFocus = true
|
|
130
|
-
Log.d(TAG, " isRestoringComposeFocus=true (proxy has Android focus)")
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// setSelection triggers a selection change (lastSelectionStart starts at -1),
|
|
134
|
-
// guaranteeing the watcher fires on the next pre-draw frame even if focus
|
|
135
|
-
// was just transferred.
|
|
136
|
-
focusProxy.setSelection(0)
|
|
137
|
-
Log.d(TAG, " proxy selectionStart=${focusProxy.selectionStart} layout=${focusProxy.layout != null}")
|
|
138
|
-
|
|
139
|
-
// Log absolute screen position — this is what keyboard-controller reads for scroll calculation
|
|
140
|
-
val loc = IntArray(2)
|
|
141
|
-
focusProxy.getLocationOnScreen(loc)
|
|
142
|
-
Log.d(TAG, " proxy screenLocation x=${loc[0]} y=${loc[1]} → absoluteY for KBC=${loc[1]}px")
|
|
143
|
-
Log.d(TAG, "──────────────────────────")
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
private fun clearFocusProxy() {
|
|
147
|
-
Log.d(TAG, "clearFocusProxy: proxy.isFocused=${focusProxy.isFocused} hasFocus=${focusProxy.hasFocus()}")
|
|
148
|
-
focusProxy.clearFocus()
|
|
149
|
-
Log.d(TAG, "clearFocusProxy: after clearFocus isFocused=${focusProxy.isFocused}")
|
|
150
85
|
}
|
|
151
86
|
|
|
152
87
|
/**
|
|
153
|
-
*
|
|
154
|
-
* Compose). At this point KBC's listener has already cleared lastFocusedInput (KBC registered
|
|
155
|
-
* its ViewTreeObserver listener before us → it fires first). We post restoreKbcTracking() to
|
|
156
|
-
* run after all synchronous focus-change handlers complete.
|
|
157
|
-
*/
|
|
158
|
-
private val proxyFocusLostListener =
|
|
159
|
-
ViewTreeObserver.OnGlobalFocusChangeListener { oldFocus, newFocus ->
|
|
160
|
-
// Fire for ANY proxy focus loss while we're in the restoration dance.
|
|
161
|
-
// newFocus can be null (proxy→null→AndroidComposeView, two steps on first focus)
|
|
162
|
-
// or AndroidComposeView directly (proxy→AndroidComposeView, subsequent focuses).
|
|
163
|
-
// Both cases need restoreKbcTracking(); KBC's null→AndroidComposeView transition does
|
|
164
|
-
// NOT clear lastFocusedInput, so restoring it once is enough for both paths.
|
|
165
|
-
if (oldFocus == focusProxy && isRestoringComposeFocus) {
|
|
166
|
-
Log.d(
|
|
167
|
-
TAG,
|
|
168
|
-
"proxyFocusLostListener: proxy → ${newFocus?.javaClass?.simpleName ?: "null"}, posting restoreKbcTracking()",
|
|
169
|
-
)
|
|
170
|
-
post { restoreKbcTracking() }
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* EdgeToEdgeViewRegistry.get() → callback → FocusedInputObserver.
|
|
88
|
+
* EdgeToEdgeViewRegistry → KeyboardAnimationCallback + FocusedInputObserver.
|
|
176
89
|
* Null if react-native-keyboard-controller is missing or not initialized.
|
|
177
90
|
*/
|
|
178
|
-
private fun
|
|
91
|
+
private fun resolveKbcCallbackAndObserver(): Pair<Any, Any>? {
|
|
179
92
|
try {
|
|
180
93
|
val registryClass =
|
|
181
94
|
Class.forName("com.reactnativekeyboardcontroller.views.EdgeToEdgeViewRegistry")
|
|
@@ -183,7 +96,7 @@ class ControlledInputView : LinearLayout, LifecycleOwner {
|
|
|
183
96
|
val edgeToEdgeView =
|
|
184
97
|
registryClass.getDeclaredMethod("get").invoke(registryInstance)
|
|
185
98
|
?: run {
|
|
186
|
-
Log.w(TAG, "
|
|
99
|
+
Log.w(TAG, "resolveKbcCallbackAndObserver: EdgeToEdgeViewRegistry.get() == null")
|
|
187
100
|
return null
|
|
188
101
|
}
|
|
189
102
|
|
|
@@ -192,14 +105,14 @@ class ControlledInputView : LinearLayout, LifecycleOwner {
|
|
|
192
105
|
it.type.simpleName == "KeyboardAnimationCallback"
|
|
193
106
|
}
|
|
194
107
|
?: run {
|
|
195
|
-
Log.w(TAG, "
|
|
108
|
+
Log.w(TAG, "resolveKbcCallbackAndObserver: KeyboardAnimationCallback field not found")
|
|
196
109
|
return null
|
|
197
110
|
}
|
|
198
111
|
callbackField.isAccessible = true
|
|
199
112
|
val callback =
|
|
200
113
|
callbackField.get(edgeToEdgeView)
|
|
201
114
|
?: run {
|
|
202
|
-
Log.w(TAG, "
|
|
115
|
+
Log.w(TAG, "resolveKbcCallbackAndObserver: callback == null")
|
|
203
116
|
return null
|
|
204
117
|
}
|
|
205
118
|
|
|
@@ -208,35 +121,57 @@ class ControlledInputView : LinearLayout, LifecycleOwner {
|
|
|
208
121
|
it.type.simpleName == "FocusedInputObserver"
|
|
209
122
|
}
|
|
210
123
|
?: run {
|
|
211
|
-
Log.w(TAG, "
|
|
124
|
+
Log.w(TAG, "resolveKbcCallbackAndObserver: FocusedInputObserver field not found")
|
|
212
125
|
return null
|
|
213
126
|
}
|
|
214
127
|
observerField.isAccessible = true
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
128
|
+
val observer =
|
|
129
|
+
observerField.get(callback)
|
|
130
|
+
?: run {
|
|
131
|
+
Log.w(TAG, "resolveKbcCallbackAndObserver: layoutObserver == null")
|
|
132
|
+
return null
|
|
133
|
+
}
|
|
134
|
+
return Pair(callback, observer)
|
|
220
135
|
} catch (_: ClassNotFoundException) {
|
|
221
|
-
Log.d(TAG, "
|
|
136
|
+
Log.d(TAG, "resolveKbcCallbackAndObserver: keyboard-controller not on classpath")
|
|
222
137
|
return null
|
|
223
138
|
} catch (e: Exception) {
|
|
224
|
-
Log.w(TAG, "
|
|
139
|
+
Log.w(TAG, "resolveKbcCallbackAndObserver: ${e.javaClass.simpleName}: ${e.message}")
|
|
225
140
|
return null
|
|
226
141
|
}
|
|
227
142
|
}
|
|
228
143
|
|
|
229
|
-
|
|
144
|
+
private fun setKbcViewTagFocused(callback: Any) {
|
|
145
|
+
try {
|
|
146
|
+
val f = callback.javaClass.getDeclaredField("viewTagFocused")
|
|
147
|
+
f.isAccessible = true
|
|
148
|
+
f.setInt(callback, id)
|
|
149
|
+
Log.d(TAG, "setKbcViewTagFocused: viewTagFocused=$id")
|
|
150
|
+
} catch (e: Exception) {
|
|
151
|
+
Log.w(TAG, "setKbcViewTagFocused: ${e.javaClass.simpleName}: ${e.message}")
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private fun setKbcFocusedInputHolder() {
|
|
156
|
+
try {
|
|
157
|
+
val holderClass =
|
|
158
|
+
Class.forName("com.reactnativekeyboardcontroller.traversal.FocusedInputHolder")
|
|
159
|
+
val instance = holderClass.getField("INSTANCE").get(null)
|
|
160
|
+
holderClass
|
|
161
|
+
.getMethod("set", EditText::class.java)
|
|
162
|
+
.invoke(instance, kbcLayoutHost)
|
|
163
|
+
} catch (e: Exception) {
|
|
164
|
+
Log.w(TAG, "setKbcFocusedInputHolder: ${e.javaClass.simpleName}: ${e.message}")
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Approximate one line height in dp for JS customHeight. */
|
|
230
169
|
private fun approximateSelectionEndYDp(): Double {
|
|
231
170
|
viewModel.inputStyle.value?.fontSize?.toDouble()?.takeIf { it > 0 }?.let { return it }
|
|
232
171
|
val dm = resources.displayMetrics
|
|
233
|
-
return (
|
|
172
|
+
return (kbcLayoutHost.textSize / dm.density).toDouble().coerceAtLeast(12.0)
|
|
234
173
|
}
|
|
235
174
|
|
|
236
|
-
/**
|
|
237
|
-
* Synthetic topFocusedInputSelectionChanged without a compile dependency on KBC.
|
|
238
|
-
* Helps older KeyboardAwareScrollView when proxy never gets android.text.Layout in time.
|
|
239
|
-
*/
|
|
240
175
|
private fun dispatchSyntheticKbcSelectionEvent(observer: Any) {
|
|
241
176
|
val reactContext = context as? ReactContext ?: return
|
|
242
177
|
try {
|
|
@@ -282,27 +217,34 @@ class ControlledInputView : LinearLayout, LifecycleOwner {
|
|
|
282
217
|
}
|
|
283
218
|
|
|
284
219
|
/**
|
|
285
|
-
*
|
|
286
|
-
*
|
|
220
|
+
* Pushes ControlledInput state into KBC without stealing Compose focus:
|
|
221
|
+
* viewTagFocused, lastFocusedInput, FocusedInputHolder, syncUpLayout, synthetic selection.
|
|
287
222
|
*/
|
|
288
|
-
private fun
|
|
289
|
-
Log.d(TAG, "
|
|
290
|
-
|
|
291
|
-
|
|
223
|
+
private fun syncKeyboardControllerFocusedInput() {
|
|
224
|
+
Log.d(TAG, "syncKeyboardControllerFocusedInput: id=$id")
|
|
225
|
+
kbcLayoutHost.id = id
|
|
226
|
+
viewModel.inputStyle.value?.fontSize?.toFloat()?.let {
|
|
227
|
+
kbcLayoutHost.setTextSize(TypedValue.COMPLEX_UNIT_SP, it)
|
|
228
|
+
}
|
|
292
229
|
|
|
230
|
+
val (callback, observer) = resolveKbcCallbackAndObserver() ?: return
|
|
231
|
+
|
|
232
|
+
setKbcViewTagFocused(callback)
|
|
233
|
+
setKbcFocusedInputHolder()
|
|
234
|
+
|
|
235
|
+
try {
|
|
293
236
|
val lastFocusedField = observer.javaClass.getDeclaredField("lastFocusedInput")
|
|
294
237
|
lastFocusedField.isAccessible = true
|
|
295
|
-
lastFocusedField.set(observer,
|
|
296
|
-
Log.d(TAG, "restoreKbcTracking: lastFocusedInput set to focusProxy")
|
|
238
|
+
lastFocusedField.set(observer, kbcLayoutHost)
|
|
297
239
|
|
|
298
240
|
val syncMethod = observer.javaClass.getDeclaredMethod("syncUpLayout")
|
|
299
241
|
syncMethod.isAccessible = true
|
|
300
242
|
syncMethod.invoke(observer)
|
|
301
|
-
Log.d(TAG, "
|
|
243
|
+
Log.d(TAG, "syncKeyboardControllerFocusedInput: syncUpLayout() ok")
|
|
302
244
|
|
|
303
245
|
dispatchSyntheticKbcSelectionEvent(observer)
|
|
304
246
|
} catch (e: Exception) {
|
|
305
|
-
Log.w(TAG, "
|
|
247
|
+
Log.w(TAG, "syncKeyboardControllerFocusedInput: ${e.javaClass.simpleName}: ${e.message}")
|
|
306
248
|
}
|
|
307
249
|
}
|
|
308
250
|
|
|
@@ -310,19 +252,15 @@ class ControlledInputView : LinearLayout, LifecycleOwner {
|
|
|
310
252
|
|
|
311
253
|
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
|
|
312
254
|
super.onLayout(changed, l, t, r, b)
|
|
313
|
-
|
|
314
|
-
// the correct width/height/absolutePosition when the proxy is focused.
|
|
315
|
-
focusProxy.layout(0, 0, width, height)
|
|
255
|
+
kbcLayoutHost.layout(0, 0, width, height)
|
|
316
256
|
if (changed) {
|
|
317
257
|
val loc = IntArray(2)
|
|
318
258
|
getLocationOnScreen(loc)
|
|
319
259
|
Log.d(TAG, "onLayout: view=${width}x${height} screenX=${loc[0]} screenY=${loc[1]}")
|
|
320
|
-
Log.d(TAG, "onLayout: proxy=${focusProxy.width}x${focusProxy.height} (should match view)")
|
|
321
260
|
}
|
|
322
261
|
}
|
|
323
262
|
|
|
324
263
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
|
325
|
-
// Do not measure ComposeView until attached to a window.
|
|
326
264
|
if (shouldUseAndroidLayout && !isAttachedToWindow) {
|
|
327
265
|
setMeasuredDimension(
|
|
328
266
|
MeasureSpec.getSize(widthMeasureSpec).coerceAtLeast(0),
|
|
@@ -333,7 +271,6 @@ class ControlledInputView : LinearLayout, LifecycleOwner {
|
|
|
333
271
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
|
334
272
|
}
|
|
335
273
|
|
|
336
|
-
// Fabric/Yoga often won't drive Android layout for native children.
|
|
337
274
|
override fun requestLayout() {
|
|
338
275
|
super.requestLayout()
|
|
339
276
|
if (shouldUseAndroidLayout) {
|
|
@@ -353,14 +290,11 @@ class ControlledInputView : LinearLayout, LifecycleOwner {
|
|
|
353
290
|
override fun onAttachedToWindow() {
|
|
354
291
|
super.onAttachedToWindow()
|
|
355
292
|
Log.d(TAG, "onAttachedToWindow: id=$id")
|
|
356
|
-
viewTreeObserver.addOnGlobalFocusChangeListener(proxyFocusLostListener)
|
|
357
293
|
bindComposeToWindowLifecycle()
|
|
358
294
|
}
|
|
359
295
|
|
|
360
296
|
override fun onDetachedFromWindow() {
|
|
361
297
|
Log.d(TAG, "onDetachedFromWindow: id=$id")
|
|
362
|
-
viewTreeObserver.removeOnGlobalFocusChangeListener(proxyFocusLostListener)
|
|
363
|
-
isRestoringComposeFocus = false
|
|
364
298
|
if (usesLocalFallbackLifecycle) {
|
|
365
299
|
lifecycleRegistry.currentState = Lifecycle.State.CREATED
|
|
366
300
|
}
|
|
@@ -406,12 +340,10 @@ class ControlledInputView : LinearLayout, LifecycleOwner {
|
|
|
406
340
|
|
|
407
341
|
fun blur() {
|
|
408
342
|
Log.d(TAG, "blur() called from JS ref")
|
|
409
|
-
isRestoringComposeFocus = false
|
|
410
343
|
blurSignal.value = blurSignal.value + 1
|
|
411
344
|
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
|
412
345
|
imm.hideSoftInputFromWindow(windowToken, 0)
|
|
413
346
|
clearFocus()
|
|
414
|
-
clearFocusProxy()
|
|
415
347
|
}
|
|
416
348
|
|
|
417
349
|
fun focus() {
|
|
@@ -431,7 +363,7 @@ class ControlledInputView : LinearLayout, LifecycleOwner {
|
|
|
431
363
|
|
|
432
364
|
viewModel = JetpackComposeViewModel()
|
|
433
365
|
|
|
434
|
-
addView(
|
|
366
|
+
addView(kbcLayoutHost)
|
|
435
367
|
|
|
436
368
|
composeView = ComposeView(context).also { cv ->
|
|
437
369
|
cv.layoutParams = LayoutParams(
|
|
@@ -483,47 +415,21 @@ class ControlledInputView : LinearLayout, LifecycleOwner {
|
|
|
483
415
|
)
|
|
484
416
|
},
|
|
485
417
|
onFocus = {
|
|
486
|
-
Log.d(TAG, "Compose onFocus id=$id
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
isRestoringComposeFocus = false
|
|
494
|
-
} else {
|
|
495
|
-
val surfaceId = UIManagerHelper.getSurfaceId(context)
|
|
496
|
-
val viewId = this@ControlledInputView.id
|
|
497
|
-
UIManagerHelper
|
|
498
|
-
.getEventDispatcherForReactTag(context as ReactContext, viewId)
|
|
499
|
-
?.dispatchEvent(FocusEvent(surfaceId, viewId))
|
|
500
|
-
requestFocusProxy()
|
|
501
|
-
}
|
|
418
|
+
Log.d(TAG, "Compose onFocus id=$id")
|
|
419
|
+
val surfaceId = UIManagerHelper.getSurfaceId(context)
|
|
420
|
+
val viewId = this@ControlledInputView.id
|
|
421
|
+
UIManagerHelper
|
|
422
|
+
.getEventDispatcherForReactTag(context as ReactContext, viewId)
|
|
423
|
+
?.dispatchEvent(FocusEvent(surfaceId, viewId))
|
|
424
|
+
post { syncKeyboardControllerFocusedInput() }
|
|
502
425
|
},
|
|
503
426
|
onBlur = {
|
|
504
|
-
Log.d(TAG, "Compose onBlur id=$id
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
post {
|
|
511
|
-
// Give AndroidComposeView Android focus back (needed for showSoftInput to work)
|
|
512
|
-
composeView.requestFocus()
|
|
513
|
-
// Trigger BasicTextField to re-gain Compose focus → shows keyboard → fires onFocus
|
|
514
|
-
focusSignal.value = focusSignal.value + 1
|
|
515
|
-
}
|
|
516
|
-
} else {
|
|
517
|
-
// Real blur (user dismissed keyboard / tapped elsewhere)
|
|
518
|
-
Log.d(TAG, " → real blur: dispatching BlurEvent")
|
|
519
|
-
isRestoringComposeFocus = false
|
|
520
|
-
val surfaceId = UIManagerHelper.getSurfaceId(context)
|
|
521
|
-
val viewId = this@ControlledInputView.id
|
|
522
|
-
UIManagerHelper
|
|
523
|
-
.getEventDispatcherForReactTag(context as ReactContext, viewId)
|
|
524
|
-
?.dispatchEvent(BlurEvent(surfaceId, viewId))
|
|
525
|
-
clearFocusProxy()
|
|
526
|
-
}
|
|
427
|
+
Log.d(TAG, "Compose onBlur id=$id")
|
|
428
|
+
val surfaceId = UIManagerHelper.getSurfaceId(context)
|
|
429
|
+
val viewId = this@ControlledInputView.id
|
|
430
|
+
UIManagerHelper
|
|
431
|
+
.getEventDispatcherForReactTag(context as ReactContext, viewId)
|
|
432
|
+
?.dispatchEvent(BlurEvent(surfaceId, viewId))
|
|
527
433
|
},
|
|
528
434
|
focusRequester = focusRequester
|
|
529
435
|
)
|
package/package.json
CHANGED