2121import android .util .Log ;
2222import android .view .ActionMode ;
2323import android .view .Gravity ;
24+ import android .view .KeyEvent ;
2425import android .view .Menu ;
2526import android .view .MenuItem ;
27+ import android .view .inputmethod .EditorInfo ;
2628import android .view .inputmethod .InputMethodManager ;
2729import android .widget .LinearLayout ;
2830import android .widget .ScrollView ;
3537import com .facebook .react .bridge .ReadableMap ;
3638import com .facebook .react .bridge .WritableMap ;
3739import com .facebook .react .uimanager .Spacing ;
40+ import com .facebook .react .uimanager .events .EventDispatcher ;
3841import com .facebook .react .uimanager .events .RCTEventEmitter ;
3942import com .facebook .react .views .text .ReactFontManager ;
4043import com .facebook .react .views .view .ReactViewBackgroundDrawable ;
@@ -66,6 +69,8 @@ public class VariableTextInput extends LinearLayout {
6669 private SpannableString mSpannableString ;
6770 private Editable mEditable ;
6871 private ReactViewBackgroundDrawable reactViewBackgroundDrawable ;
72+ private @ Nullable String mReturnKeyType ;
73+ private boolean mDisableFullscreen ;
6974 private static final InputFilter [] EMPTY_FILTERS = new InputFilter [0 ];
7075 public VariableTextInput (Context context ) {
7176 super (context );
@@ -80,6 +85,8 @@ public VariableTextInput(Context context) {
8085 editText .setInputType (editText .getInputType () | InputType .TYPE_TEXT_FLAG_CAP_SENTENCES
8186 | InputType .TYPE_TEXT_FLAG_AUTO_CORRECT | InputType .TYPE_TEXT_FLAG_MULTI_LINE );
8287 editText .setPadding (0 , 0 , 0 , 0 );
88+ editText .setImeOptions (EditorInfo .IME_ACTION_NONE );
89+ mDisableFullscreen = false ;
8390 // This was used in conjunction with setting raw input type for selecting lock
8491 // notes.
8592 // However, it causes the keyboard to not come up for editing existing notes.
@@ -198,6 +205,55 @@ public void onPaste() {
198205 }
199206 }
200207 });
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+ });
201257 if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .M ) {
202258 editText .setCustomSelectionActionModeCallback (new ActionMode .Callback () {
203259 @ Override
@@ -377,7 +433,9 @@ public void setBorderWidth(int position, float width) {
377433 public void setBorderColor (int position , float color , float alpha ) {
378434 reactViewBackgroundDrawable .setBorderColor (position , color , alpha );
379435 }
380-
436+ public void setSubmitBehavior (String submitBehavior ) {
437+ editText .setSubmitBehavior (submitBehavior );
438+ }
381439 public int getBorderColor (int position ) {
382440 return reactViewBackgroundDrawable .getBorderColor (position );
383441 }
@@ -472,8 +530,55 @@ public void setPlaceholder(String placeholder) {
472530 public void setPlaceholderColor (int placeholderColor ){
473531 editText .setHintTextColor (placeholderColor );
474532 }
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 ;
477582 }
478583 public void setFontSize (Integer fontSize ) {
479584 editText .setTextSize (fontSize );
0 commit comments