7
7
8
8
package com .facebook .react .views .textinput ;
9
9
10
- import static com .facebook .react .uimanager .UIManagerHelper .getReactContext ;
11
-
12
10
import android .content .Context ;
13
11
import android .content .res .ColorStateList ;
14
12
import android .graphics .BlendMode ;
17
15
import android .graphics .PorterDuff ;
18
16
import android .graphics .drawable .Drawable ;
19
17
import android .os .Build ;
20
- import android .text .Editable ;
21
18
import android .text .InputFilter ;
22
19
import android .text .InputType ;
23
20
import android .text .Layout ;
24
21
import android .text .Spannable ;
25
22
import android .text .SpannableStringBuilder ;
26
- import android .text .TextWatcher ;
27
23
import android .view .Gravity ;
28
24
import android .view .View ;
29
25
import android .view .ViewGroup ;
33
29
import androidx .autofill .HintConstants ;
34
30
import androidx .core .content .ContextCompat ;
35
31
import com .facebook .common .logging .FLog ;
36
- import com .facebook .infer .annotation .Assertions ;
37
32
import com .facebook .react .bridge .Dynamic ;
38
33
import com .facebook .react .bridge .ReactContext ;
39
34
import com .facebook .react .bridge .ReactSoftExceptionLogger ;
40
35
import com .facebook .react .bridge .ReadableArray ;
41
36
import com .facebook .react .bridge .ReadableType ;
42
- import com .facebook .react .bridge .WritableMap ;
43
- import com .facebook .react .bridge .WritableNativeMap ;
44
37
import com .facebook .react .common .MapBuilder ;
45
38
import com .facebook .react .common .ReactConstants ;
46
39
import com .facebook .react .common .mapbuffer .MapBuffer ;
50
43
import com .facebook .react .uimanager .LayoutShadowNode ;
51
44
import com .facebook .react .uimanager .LengthPercentage ;
52
45
import com .facebook .react .uimanager .LengthPercentageType ;
53
- import com .facebook .react .uimanager .PixelUtil ;
54
46
import com .facebook .react .uimanager .ReactStylesDiffMap ;
55
47
import com .facebook .react .uimanager .Spacing ;
56
48
import com .facebook .react .uimanager .StateWrapper ;
65
57
import com .facebook .react .uimanager .style .BorderStyle ;
66
58
import com .facebook .react .uimanager .style .LogicalEdge ;
67
59
import com .facebook .react .views .imagehelper .ResourceDrawableIdHelper ;
68
- import com .facebook .react .views .scroll .ScrollEvent ;
69
60
import com .facebook .react .views .scroll .ScrollEventType ;
70
61
import com .facebook .react .views .text .DefaultStyleValuesUtil ;
71
62
import com .facebook .react .views .text .ReactBaseTextShadowNode ;
@@ -453,7 +444,7 @@ private void setAutofillHints(ReactEditText view, String... hints) {
453
444
@ ReactProp (name = "onSelectionChange" , defaultBoolean = false )
454
445
public void setOnSelectionChange (final ReactEditText view , boolean onSelectionChange ) {
455
446
if (onSelectionChange ) {
456
- view .setSelectionWatcher (new ReactSelectionWatcher (view ));
447
+ view .setSelectionWatcher (new ReactTextSelectionWatcher (view ));
457
448
} else {
458
449
view .setSelectionWatcher (null );
459
450
}
@@ -467,7 +458,7 @@ public void setSubmitBehavior(ReactEditText view, @Nullable String submitBehavio
467
458
@ ReactProp (name = "onContentSizeChange" , defaultBoolean = false )
468
459
public void setOnContentSizeChange (final ReactEditText view , boolean onContentSizeChange ) {
469
460
if (onContentSizeChange ) {
470
- view .setContentSizeWatcher (new ReactContentSizeWatcher (view ));
461
+ view .setContentSizeWatcher (new ReactTextContentSizeWatcher (view ));
471
462
} else {
472
463
view .setContentSizeWatcher (null );
473
464
}
@@ -476,7 +467,7 @@ public void setOnContentSizeChange(final ReactEditText view, boolean onContentSi
476
467
@ ReactProp (name = "onScroll" , defaultBoolean = false )
477
468
public void setOnScroll (final ReactEditText view , boolean onScroll ) {
478
469
if (onScroll ) {
479
- view .setScrollWatcher (new ReactScrollWatcher (view ));
470
+ view .setScrollWatcher (new ReactTextScrollWatcher (view ));
480
471
} else {
481
472
view .setScrollWatcher (null );
482
473
}
@@ -1051,73 +1042,12 @@ private static void updateStagedInputTypeFlag(
1051
1042
view .setStagedInputType ((view .getStagedInputType () & ~flagsToUnset ) | flagsToSet );
1052
1043
}
1053
1044
1045
+ @ Nullable
1054
1046
private static EventDispatcher getEventDispatcher (
1055
1047
ReactContext reactContext , ReactEditText editText ) {
1056
1048
return UIManagerHelper .getEventDispatcherForReactTag (reactContext , editText .getId ());
1057
1049
}
1058
1050
1059
- private final class ReactTextInputTextWatcher implements TextWatcher {
1060
- private final ReactEditText mEditText ;
1061
- private final EventDispatcher mEventDispatcher ;
1062
- private final int mSurfaceId ;
1063
- @ Nullable private String mPreviousText ;
1064
-
1065
- public ReactTextInputTextWatcher (
1066
- final ReactContext reactContext , final ReactEditText editText ) {
1067
- mEventDispatcher = getEventDispatcher (reactContext , editText );
1068
- mEditText = editText ;
1069
- mPreviousText = null ;
1070
- mSurfaceId = UIManagerHelper .getSurfaceId (reactContext );
1071
- }
1072
-
1073
- @ Override
1074
- public void beforeTextChanged (CharSequence s , int start , int count , int after ) {
1075
- // Incoming charSequence gets mutated before onTextChanged() is invoked
1076
- mPreviousText = s .toString ();
1077
- }
1078
-
1079
- @ Override
1080
- public void onTextChanged (CharSequence s , int start , int before , int count ) {
1081
- if (mEditText .mDisableTextDiffing ) {
1082
- return ;
1083
- }
1084
-
1085
- // Rearranging the text (i.e. changing between singleline and multiline attributes) can
1086
- // also trigger onTextChanged, call the event in JS only when the text actually changed
1087
- if (count == 0 && before == 0 ) {
1088
- return ;
1089
- }
1090
-
1091
- Assertions .assertNotNull (mPreviousText );
1092
- String newText = s .toString ().substring (start , start + count );
1093
- String oldText = mPreviousText .substring (start , start + before );
1094
- // Don't send same text changes
1095
- if (count == before && newText .equals (oldText )) {
1096
- return ;
1097
- }
1098
-
1099
- StateWrapper stateWrapper = mEditText .getStateWrapper ();
1100
-
1101
- if (stateWrapper != null ) {
1102
- WritableMap newStateData = new WritableNativeMap ();
1103
- newStateData .putInt ("mostRecentEventCount" , mEditText .incrementAndGetEventCounter ());
1104
- newStateData .putInt ("opaqueCacheId" , mEditText .getId ());
1105
- stateWrapper .updateState (newStateData );
1106
- }
1107
-
1108
- // The event that contains the event counter and updates it must be sent first.
1109
- mEventDispatcher .dispatchEvent (
1110
- new ReactTextChangedEvent (
1111
- mSurfaceId ,
1112
- mEditText .getId (),
1113
- s .toString (),
1114
- mEditText .incrementAndGetEventCounter ()));
1115
- }
1116
-
1117
- @ Override
1118
- public void afterTextChanged (Editable s ) {}
1119
- }
1120
-
1121
1051
@ Override
1122
1052
protected void addEventEmitters (
1123
1053
final ThemedReactContext reactContext , final ReactEditText editText ) {
@@ -1188,130 +1118,6 @@ protected void addEventEmitters(
1188
1118
});
1189
1119
}
1190
1120
1191
- private static class ReactContentSizeWatcher implements ContentSizeWatcher {
1192
- private final ReactEditText mEditText ;
1193
- private final EventDispatcher mEventDispatcher ;
1194
- private final int mSurfaceId ;
1195
- private int mPreviousContentWidth = 0 ;
1196
- private int mPreviousContentHeight = 0 ;
1197
-
1198
- public ReactContentSizeWatcher (ReactEditText editText ) {
1199
- mEditText = editText ;
1200
- ReactContext reactContext = getReactContext (editText );
1201
- mEventDispatcher = getEventDispatcher (reactContext , editText );
1202
- mSurfaceId = UIManagerHelper .getSurfaceId (reactContext );
1203
- }
1204
-
1205
- @ Override
1206
- public void onLayout () {
1207
- if (mEventDispatcher == null ) {
1208
- return ;
1209
- }
1210
-
1211
- int contentWidth = mEditText .getWidth ();
1212
- int contentHeight = mEditText .getHeight ();
1213
-
1214
- // Use instead size of text content within EditText when available
1215
- if (mEditText .getLayout () != null ) {
1216
- contentWidth =
1217
- mEditText .getCompoundPaddingLeft ()
1218
- + mEditText .getLayout ().getWidth ()
1219
- + mEditText .getCompoundPaddingRight ();
1220
- contentHeight =
1221
- mEditText .getCompoundPaddingTop ()
1222
- + mEditText .getLayout ().getHeight ()
1223
- + mEditText .getCompoundPaddingBottom ();
1224
- }
1225
-
1226
- if (contentWidth != mPreviousContentWidth || contentHeight != mPreviousContentHeight ) {
1227
- mPreviousContentHeight = contentHeight ;
1228
- mPreviousContentWidth = contentWidth ;
1229
-
1230
- mEventDispatcher .dispatchEvent (
1231
- new ReactContentSizeChangedEvent (
1232
- mSurfaceId ,
1233
- mEditText .getId (),
1234
- PixelUtil .toDIPFromPixel (contentWidth ),
1235
- PixelUtil .toDIPFromPixel (contentHeight )));
1236
- }
1237
- }
1238
- }
1239
-
1240
- private static class ReactSelectionWatcher implements SelectionWatcher {
1241
- private final ReactEditText mReactEditText ;
1242
- private final EventDispatcher mEventDispatcher ;
1243
- private final int mSurfaceId ;
1244
- private int mPreviousSelectionStart ;
1245
- private int mPreviousSelectionEnd ;
1246
-
1247
- public ReactSelectionWatcher (ReactEditText editText ) {
1248
- mReactEditText = editText ;
1249
- ReactContext reactContext = getReactContext (editText );
1250
- mEventDispatcher = getEventDispatcher (reactContext , editText );
1251
- mSurfaceId = UIManagerHelper .getSurfaceId (reactContext );
1252
- }
1253
-
1254
- @ Override
1255
- public void onSelectionChanged (int start , int end ) {
1256
- // Android will call us back for both the SELECTION_START span and SELECTION_END span in text
1257
- // To prevent double calling back into js we cache the result of the previous call and only
1258
- // forward it on if we have new values
1259
-
1260
- // Apparently Android might call this with an end value that is less than the start value
1261
- // Lets normalize them. See https://github.com/facebook/react-native/issues/18579
1262
- int realStart = Math .min (start , end );
1263
- int realEnd = Math .max (start , end );
1264
-
1265
- if (mPreviousSelectionStart != realStart || mPreviousSelectionEnd != realEnd ) {
1266
- mEventDispatcher .dispatchEvent (
1267
- new ReactTextInputSelectionEvent (
1268
- mSurfaceId , mReactEditText .getId (), realStart , realEnd ));
1269
-
1270
- mPreviousSelectionStart = realStart ;
1271
- mPreviousSelectionEnd = realEnd ;
1272
- }
1273
- }
1274
- }
1275
-
1276
- private static class ReactScrollWatcher implements ScrollWatcher {
1277
- private final ReactEditText mReactEditText ;
1278
- private final EventDispatcher mEventDispatcher ;
1279
- private final int mSurfaceId ;
1280
- private int mPreviousHorizontal ;
1281
- private int mPreviousVert ;
1282
-
1283
- public ReactScrollWatcher (ReactEditText editText ) {
1284
- mReactEditText = editText ;
1285
- ReactContext reactContext = getReactContext (editText );
1286
- mEventDispatcher = getEventDispatcher (reactContext , editText );
1287
- mSurfaceId = UIManagerHelper .getSurfaceId (reactContext );
1288
- }
1289
-
1290
- @ Override
1291
- public void onScrollChanged (int horiz , int vert , int oldHoriz , int oldVert ) {
1292
- if (mPreviousHorizontal != horiz || mPreviousVert != vert ) {
1293
- ScrollEvent event =
1294
- ScrollEvent .obtain (
1295
- mSurfaceId ,
1296
- mReactEditText .getId (),
1297
- ScrollEventType .SCROLL ,
1298
- horiz ,
1299
- vert ,
1300
- 0f , // can't get x velocity
1301
- 0f , // can't get y velocity
1302
- 0 , // can't get content width
1303
- 0 , // can't get content height
1304
- mReactEditText .getWidth (),
1305
- mReactEditText .getHeight ());
1306
-
1307
- mEventDispatcher .dispatchEvent (event );
1308
-
1309
- mPreviousHorizontal = horiz ;
1310
- mPreviousVert = vert ;
1311
- }
1312
- }
1313
- }
1314
-
1315
1121
@ Override
1316
1122
public @ Nullable Map <String , Object > getExportedViewConstants () {
1317
1123
return MapBuilder .of (
0 commit comments