21
21
import android .util .Log ;
22
22
import android .view .ActionMode ;
23
23
import android .view .Gravity ;
24
+ import android .view .KeyEvent ;
24
25
import android .view .Menu ;
25
26
import android .view .MenuItem ;
27
+ import android .view .inputmethod .EditorInfo ;
26
28
import android .view .inputmethod .InputMethodManager ;
27
29
import android .widget .LinearLayout ;
28
30
import android .widget .ScrollView ;
35
37
import com .facebook .react .bridge .ReadableMap ;
36
38
import com .facebook .react .bridge .WritableMap ;
37
39
import com .facebook .react .uimanager .Spacing ;
40
+ import com .facebook .react .uimanager .events .EventDispatcher ;
38
41
import com .facebook .react .uimanager .events .RCTEventEmitter ;
39
42
import com .facebook .react .views .text .ReactFontManager ;
40
43
import com .facebook .react .views .view .ReactViewBackgroundDrawable ;
@@ -66,6 +69,8 @@ public class VariableTextInput extends LinearLayout {
66
69
private SpannableString mSpannableString ;
67
70
private Editable mEditable ;
68
71
private ReactViewBackgroundDrawable reactViewBackgroundDrawable ;
72
+ private @ Nullable String mReturnKeyType ;
73
+ private boolean mDisableFullscreen ;
69
74
private static final InputFilter [] EMPTY_FILTERS = new InputFilter [0 ];
70
75
public VariableTextInput (Context context ) {
71
76
super (context );
@@ -80,6 +85,8 @@ public VariableTextInput(Context context) {
80
85
editText .setInputType (editText .getInputType () | InputType .TYPE_TEXT_FLAG_CAP_SENTENCES
81
86
| InputType .TYPE_TEXT_FLAG_AUTO_CORRECT | InputType .TYPE_TEXT_FLAG_MULTI_LINE );
82
87
editText .setPadding (0 , 0 , 0 , 0 );
88
+ editText .setImeOptions (EditorInfo .IME_ACTION_NONE );
89
+ mDisableFullscreen = false ;
83
90
// This was used in conjunction with setting raw input type for selecting lock
84
91
// notes.
85
92
// However, it causes the keyboard to not come up for editing existing notes.
@@ -198,6 +205,55 @@ public void onPaste() {
198
205
}
199
206
}
200
207
});
208
+ editText .setOnEditorActionListener (
209
+ new TextView .OnEditorActionListener () {
210
+ @ Override
211
+ public boolean onEditorAction (TextView v , int actionId , KeyEvent keyEvent ) {
212
+ if ((actionId & EditorInfo .IME_MASK_ACTION ) != 0 || actionId == EditorInfo .IME_NULL ) {
213
+ boolean isMultiline = true ;
214
+
215
+ boolean shouldSubmit = editText .shouldSubmitOnReturn ();
216
+ boolean shouldBlur = editText .shouldBlurOnReturn ();
217
+ // Motivation:
218
+ // * shouldSubmit => Clear focus; prevent default behavior (return true);
219
+ // * shouldBlur => Submit; prevent default behavior (return true);
220
+ // * !shouldBlur && !shouldSubmit && isMultiline => Perform default behavior (return
221
+ // false);
222
+ // * !shouldBlur && !shouldSubmit && !isMultiline => Prevent default behavior (return
223
+ // true);
224
+ if (shouldSubmit ) {
225
+ WritableMap event = Arguments .createMap ();
226
+ event .putString ("text" , editText .getText ().toString ());
227
+ final Context context = getContext ();
228
+ if (context instanceof ReactContext ) {
229
+ ((ReactContext ) context ).getJSModule (RCTEventEmitter .class ).receiveEvent (getId (), "onAndroidSubmitEditing" , event );
230
+ }
231
+ }
232
+
233
+ if (shouldBlur ) {
234
+ editText .clearFocus ();
235
+ }
236
+
237
+ // Prevent default behavior except when we want it to insert a newline.
238
+ if (shouldBlur || shouldSubmit || !isMultiline ) {
239
+ return true ;
240
+ }
241
+
242
+ // If we've reached this point, it means that the TextInput has 'submitBehavior' set
243
+ // nullish and 'multiline' set to true. But it's still possible to get IME_ACTION_NEXT
244
+ // and IME_ACTION_PREVIOUS here in case if 'disableFullscreenUI' is false and Android
245
+ // decides to render this EditText in the full screen mode (when a phone has the
246
+ // landscape orientation for example). The full screen EditText also renders an action
247
+ // button specified by the 'returnKeyType' prop. We have to prevent Android from
248
+ // requesting focus from the next/previous focusable view since it must only be
249
+ // controlled from JS.
250
+ return actionId == EditorInfo .IME_ACTION_NEXT
251
+ || actionId == EditorInfo .IME_ACTION_PREVIOUS ;
252
+ }
253
+
254
+ return true ;
255
+ }
256
+ });
201
257
if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .M ) {
202
258
editText .setCustomSelectionActionModeCallback (new ActionMode .Callback () {
203
259
@ Override
@@ -377,7 +433,9 @@ public void setBorderWidth(int position, float width) {
377
433
public void setBorderColor (int position , float color , float alpha ) {
378
434
reactViewBackgroundDrawable .setBorderColor (position , color , alpha );
379
435
}
380
-
436
+ public void setSubmitBehavior (String submitBehavior ) {
437
+ editText .setSubmitBehavior (submitBehavior );
438
+ }
381
439
public int getBorderColor (int position ) {
382
440
return reactViewBackgroundDrawable .getBorderColor (position );
383
441
}
@@ -472,8 +530,55 @@ public void setPlaceholder(String placeholder) {
472
530
public void setPlaceholderColor (int placeholderColor ){
473
531
editText .setHintTextColor (placeholderColor );
474
532
}
475
- public void setUnderLineColorAndroid (Integer color ) {
476
- editText .setBackgroundTintList (ColorStateList .valueOf (color ));
533
+ public void setReturnKeyType (String returnKeyType ) {
534
+ mReturnKeyType = returnKeyType ;
535
+ updateImeOptions ();
536
+ }
537
+ private void updateImeOptions () {
538
+ // Default to IME_ACTION_DONE
539
+ int returnKeyFlag = EditorInfo .IME_ACTION_DONE ;
540
+ if (mReturnKeyType != null ) {
541
+ switch (mReturnKeyType ) {
542
+ case "go" :
543
+ returnKeyFlag = EditorInfo .IME_ACTION_GO ;
544
+ break ;
545
+ case "next" :
546
+ returnKeyFlag = EditorInfo .IME_ACTION_NEXT ;
547
+ break ;
548
+ case "none" :
549
+ returnKeyFlag = EditorInfo .IME_ACTION_NONE ;
550
+ break ;
551
+ case "previous" :
552
+ returnKeyFlag = EditorInfo .IME_ACTION_PREVIOUS ;
553
+ break ;
554
+ case "search" :
555
+ returnKeyFlag = EditorInfo .IME_ACTION_SEARCH ;
556
+ break ;
557
+ case "send" :
558
+ returnKeyFlag = EditorInfo .IME_ACTION_SEND ;
559
+ break ;
560
+ case "done" :
561
+ returnKeyFlag = EditorInfo .IME_ACTION_DONE ;
562
+ break ;
563
+ }
564
+ }
565
+
566
+ if (mDisableFullscreen ) {
567
+ setImeOptions (returnKeyFlag | EditorInfo .IME_FLAG_NO_FULLSCREEN );
568
+ } else {
569
+ setImeOptions (returnKeyFlag );
570
+ }
571
+ }
572
+ public void setImeActionLabel (String returnKeyLabel ,int imID ){
573
+ editText .setImeActionLabel (returnKeyLabel ,imID );
574
+ }
575
+ public void setDisableFullscreenUI (boolean disableFullscreenUI ) {
576
+ mDisableFullscreen = disableFullscreenUI ;
577
+ updateImeOptions ();
578
+ }
579
+
580
+ public boolean getDisableFullscreenUI () {
581
+ return mDisableFullscreen ;
477
582
}
478
583
public void setFontSize (Integer fontSize ) {
479
584
editText .setTextSize (fontSize );
0 commit comments