@@ -50,14 +50,14 @@ import android.widget.EditText
50
50
import android.widget.TextView
51
51
import androidx.annotation.ColorInt
52
52
import androidx.annotation.GravityInt
53
- import androidx.core.text.toSpanned
54
53
import androidx.core.util.ObjectsCompat
55
54
import androidx.core.view.ViewCompat
56
55
import com.facebook.litho.ComponentContext
57
56
import com.facebook.litho.ComponentScope
58
57
import com.facebook.litho.LithoPrimitive
59
58
import com.facebook.litho.PrimitiveComponent
60
59
import com.facebook.litho.PrimitiveComponentScope
60
+ import com.facebook.litho.State
61
61
import com.facebook.litho.Style
62
62
import com.facebook.litho.ThreadUtils.assertMainThread
63
63
import com.facebook.litho.annotations.Hook
@@ -237,7 +237,20 @@ class ExperimentalTextInput(
237
237
override fun PrimitiveComponentScope.render (): LithoPrimitive {
238
238
val mountedView = useState { AtomicReference <EditTextWithEventHandlers ?>() }
239
239
val savedText = useState { AtomicReference (initialText) }
240
+ val copyInitialTextInTextInputRender =
241
+ useState { ComponentsConfiguration .copyInitialTextInTextInputRender }.value
242
+
243
+ // control
240
244
val measureSeqNumber = useState { 0 }
245
+ // test
246
+ val textForMeasure =
247
+ useState<CharSequence > {
248
+ if (copyInitialTextInTextInputRender) {
249
+ initialText.toString()
250
+ } else {
251
+ initialText
252
+ }
253
+ }
241
254
242
255
val resolvedHighlightColor = useCached {
243
256
if (highlightColor != null ) {
@@ -289,6 +302,8 @@ class ExperimentalTextInput(
289
302
movementMethod = movementMethod,
290
303
savedText = savedText.value,
291
304
measureSeqNumber = measureSeqNumber.value,
305
+ copyInitialTextInTextInputRender = copyInitialTextInTextInputRender,
306
+ textForMeasure = textForMeasure,
292
307
),
293
308
mountBehavior =
294
309
MountBehavior (
@@ -304,10 +319,20 @@ class ExperimentalTextInput(
304
319
305
320
// Controller
306
321
withDescription(" text-input-controller" ) {
307
- bind(textInputController, savedText.value, measureSeqNumber) { editText ->
308
- textInputController?.bind(editText, savedText.value, measureSeqNumber)
309
- onUnbind { textInputController?.unbind() }
310
- }
322
+ bind(
323
+ textInputController,
324
+ savedText.value,
325
+ measureSeqNumber,
326
+ copyInitialTextInTextInputRender,
327
+ textForMeasure) { editText ->
328
+ textInputController?.bind(
329
+ editText,
330
+ savedText.value,
331
+ measureSeqNumber,
332
+ copyInitialTextInTextInputRender,
333
+ textForMeasure)
334
+ onUnbind { textInputController?.unbind() }
335
+ }
311
336
}
312
337
// OnMount
313
338
withDescription(" text-input-equivalent-mount" ) {
@@ -423,6 +448,8 @@ class ExperimentalTextInput(
423
448
editText.onInputConnection = onInputConnection
424
449
editText.onTextPasted = onTextPasted
425
450
editText.measureSeqNumber = measureSeqNumber
451
+ editText.copyInitialTextInTextInputRender = copyInitialTextInTextInputRender
452
+ editText.textForMeasure = textForMeasure
426
453
427
454
onUnbind {
428
455
editText.detachWatchers()
@@ -438,6 +465,8 @@ class ExperimentalTextInput(
438
465
editText.customInsertionActionModeCallback = null
439
466
editText.onTextPasted = null
440
467
editText.measureSeqNumber = null
468
+ editText.copyInitialTextInTextInputRender = false
469
+ editText.textForMeasure = null
441
470
}
442
471
}
443
472
}
@@ -482,6 +511,8 @@ internal class TextInputLayoutBehavior(
482
511
private val savedText : AtomicReference <CharSequence ?>,
483
512
// we're only reading it here in order to force remeasure if it gets updated
484
513
private val measureSeqNumber : Int ,
514
+ private val copyInitialTextInTextInputRender : Boolean ,
515
+ private val textForMeasure : State <CharSequence >,
485
516
) : LayoutBehavior {
486
517
override fun LayoutScope.layout (sizeConstraints : SizeConstraints ): PrimitiveLayoutResult {
487
518
val context =
@@ -528,7 +559,9 @@ internal class TextInputLayoutBehavior(
528
559
// onMeasure happens:
529
560
// 1. After initState before onMount: savedText = initText.
530
561
// 2. After onMount before onUnmount: savedText preserved from underlying editText.
531
- savedText.get())
562
+ savedText.get(),
563
+ copyInitialTextInTextInputRender,
564
+ textForMeasure)
532
565
533
566
return PrimitiveLayoutResult (
534
567
height = forMeasure.measuredHeight,
@@ -588,14 +621,18 @@ fun createAndMeasureEditText(
588
621
importantForAutofill : Int ,
589
622
autofillHints : Array <String ?>? ,
590
623
disableAutofill : Boolean ,
591
- text : CharSequence?
624
+ text : CharSequence? ,
625
+ copyInitialTextInTextInputRender : Boolean ,
626
+ textForMeasure : State <CharSequence >,
592
627
): EditText {
593
628
// The height should be the measured height of EditText with relevant params
594
629
var textToMeasure = text
595
630
val forMeasure = ForMeasureEditText (context)
596
631
// If text contains Spans, we don't want it to be mutable for the measurement case
597
- if (textToMeasure is Spannable ) {
598
- textToMeasure = textToMeasure.toSpanned()
632
+ if (copyInitialTextInTextInputRender) {
633
+ textToMeasure = textForMeasure.value
634
+ } else if (textToMeasure is Spannable ) {
635
+ textToMeasure = textToMeasure.toString()
599
636
}
600
637
if (context is MeasureContext ) {
601
638
context.withInputMethodManagerDisabled {
@@ -868,6 +905,8 @@ internal class EditTextWithEventHandlers(context: Context?) :
868
905
var onInputConnection: ((InputConnection ? , EditorInfo ) -> InputConnection )? = null
869
906
var componentContext: ComponentContext ? = null
870
907
var measureSeqNumber: com.facebook.litho.State <Int >? = null
908
+ var copyInitialTextInTextInputRender: Boolean = false
909
+ var textForMeasure: com.facebook.litho.State <CharSequence >? = null
871
910
private var textState: AtomicReference <CharSequence ?>? = null
872
911
private var textLineCount = UNMEASURED_LINE_COUNT
873
912
private var textWatcher: TextWatcher ? = null
@@ -898,7 +937,11 @@ internal class EditTextWithEventHandlers(context: Context?) :
898
937
if (this .textLineCount != UNMEASURED_LINE_COUNT &&
899
938
(this .textLineCount != lineCount) &&
900
939
(componentContext != null )) {
901
- measureSeqNumber?.update { it + 1 }
940
+ if (copyInitialTextInTextInputRender) {
941
+ textForMeasure?.update(text.toString())
942
+ } else {
943
+ measureSeqNumber?.update { it + 1 }
944
+ }
902
945
}
903
946
}
904
947
@@ -1189,15 +1232,21 @@ class TextInputController internal constructor() {
1189
1232
private var editText: EditTextWithEventHandlers ? = null
1190
1233
private var savedText: AtomicReference <CharSequence ?>? = null
1191
1234
private var measureSeqNumber: com.facebook.litho.State <Int >? = null
1235
+ private var copyInitialTextInTextInputRender: Boolean = false
1236
+ private var textForMeasure: com.facebook.litho.State <CharSequence >? = null
1192
1237
1193
1238
internal fun bind (
1194
1239
editText : EditTextWithEventHandlers ,
1195
1240
savedText : AtomicReference <CharSequence ?>,
1196
1241
measureSeqNumber : com.facebook.litho.State <Int >? ,
1242
+ copyInitialTextInTextInputRender : Boolean ,
1243
+ textForMeasure : com.facebook.litho.State <CharSequence >? ,
1197
1244
) {
1198
1245
this .editText = editText
1199
1246
this .savedText = savedText
1200
1247
this .measureSeqNumber = measureSeqNumber
1248
+ this .copyInitialTextInTextInputRender = copyInitialTextInTextInputRender
1249
+ this .textForMeasure = textForMeasure
1201
1250
}
1202
1251
1203
1252
internal fun unbind () {
@@ -1335,7 +1384,11 @@ class TextInputController internal constructor() {
1335
1384
}
1336
1385
1337
1386
private fun remeasureForUpdatedTextSync () {
1338
- measureSeqNumber?.updateSync { it + 1 }
1387
+ if (copyInitialTextInTextInputRender) {
1388
+ textForMeasure?.updateSync(savedText?.get().toString())
1389
+ } else {
1390
+ measureSeqNumber?.updateSync { it + 1 }
1391
+ }
1339
1392
}
1340
1393
}
1341
1394
0 commit comments