Anh-Tuan Mai
Anh-Tuan Mai

Reputation: 1189

Android custom soft keyboard - change KEYCODE_ENTER behavior to skip non EditText object like default soft keyboard behavior

Follow this sample https://android.googlesource.com/platform/development/+/master/samples/SoftKeyboard/ , I have my own soft keyboard. I want to modify KEYCODE_ENTER behavior.

Example: I have my activity A with its layout layout_A: EditText edt_1 + CheckBox chb_1 + EditText edt_2

The behavior of Android default soft keyboard:

focus edt_1 > KEYCODE_ENTER > skip chb_1 > focus edt_2 >> what I want

My soft keyboard:

focus edt_1 > KEYCODE_ENTER > focus chb_1 >> FAIL

Any one have source code of Android default soft keyboard? (with layout of number text keyboard and full text keyboard)

Any suggestion may help, thanks you very much.

public class SoftKeyboard extends InputMethodService implements KeyboardView.OnKeyboardActionListener

    @Override public void onStartInput(EditorInfo attribute, boolean restarting) {
        super.onStartInput(attribute, restarting);

        // Reset our state.  We want to do this even if restarting, because
        // the underlying state of the text editor could have changed in any way.
        mComposing.setLength(0);
        updateCandidates();

        if (!restarting) {
            // Clear shift states.
            mMetaState = 0;
        }

        boolean isEditText = true;

        mPredictionOn = false;
        mCompletionOn = false;
        mCompletions = null;

        //TODO: setup own behavior
        // We are now going to initialize our state based on the type of
        // text being edited.
        switch (attribute.inputType & InputType.TYPE_MASK_CLASS) {
            case InputType.TYPE_CLASS_NUMBER:
                mCurKeyboard = mNumberKeyboard;
                break;

            case InputType.TYPE_CLASS_DATETIME:
                // Numbers and dates default to the symbols keyboard, with
                // no extra features.
                mCurKeyboard = mSymbolsKeyboard;
                break;

            case InputType.TYPE_CLASS_PHONE:
                // Phones will also default to the symbols keyboard, though
                // often you will want to have a dedicated phone keyboard.
                mCurKeyboard = mSymbolsKeyboard;
                break;

            case InputType.TYPE_CLASS_TEXT:
                // This is general text editing.  We will default to the
                // normal alphabetic keyboard, and assume that we should
                // be doing predictive text (showing candidates as the
                // user types).
                mCurKeyboard = mQwertyKeyboard;
                mPredictionOn = true;

                // We now look for a few special variations of text that will
                // modify our behavior.
                int variation = attribute.inputType & InputType.TYPE_MASK_VARIATION;
                if (variation == InputType.TYPE_TEXT_VARIATION_PASSWORD ||
                        variation == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
                    // Do not display predictions / what the user is typing
                    // when they are entering a password.
                    mPredictionOn = false;
                }

                if (variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
                        || variation == InputType.TYPE_TEXT_VARIATION_URI
                        || variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
                    // Our predictions are not useful for e-mail addresses
                    // or URIs.
                    mPredictionOn = false;
                }

                if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
                    // If this is an auto-complete text view, then our predictions
                    // will not be shown and instead we will allow the editor
                    // to supply their own.  We only show the editor's
                    // candidates when in fullscreen mode, otherwise relying
                    // own it displaying its own UI.
                    mPredictionOn = false;
                    mCompletionOn = isFullscreenMode();
                }

                // We also want to look at the current state of the editor
                // to decide whether our alphabetic keyboard should start out
                // shifted.
                updateShiftKeyState(attribute);
                break;

            default:
                // For all unknown input types, default to the alphabetic
                // keyboard with no special features.
                mCurKeyboard = mNonEditTextKeyboard;
                updateShiftKeyState(attribute);
                isEditText = false;
        }

        // Update the label on the enter key, depending on what the application
        // says it will do.
        mCurKeyboard.setImeOptions(getResources(), attribute.imeOptions);

        if ((mInputView!= null) && (!isEditText)) {
            //TODO: handle non edit text case.
            handleClose();
        }
    }

Upvotes: 2

Views: 1044

Answers (3)

Anh-Tuan Mai
Anh-Tuan Mai

Reputation: 1189

My code on input keyboard service (not activity):

@Override public void onStartInput(EditorInfo attribute, boolean restarting) {
    super.onStartInput(attribute, restarting);

    ...

    if ((getCurrentInputConnection() != null) && (!isEditText))
        getCurrentInputConnection().performEditorAction(EditorInfo.IME_ACTION_NEXT);
    }
}

However, I propose dont put keycode 10 \n Enter on your keyboard but using code -4 IME ActionDone. In my example it works so much better since it let the application make focus choice, it will skip non object text and clear focus properly.

Upvotes: 1

user5156016
user5156016

Reputation:

Use the android:nextFocusDown param to specify which field you'd like to get focus when the user hits the enter key.

Upvotes: 1

vguzzi
vguzzi

Reputation: 2428

To modify enter behaviour on the soft keyboard you will have to create a custom EditText class and override onCreateInputConnections. See my example below in which I always display 'Done' instead of next when users are on this specific EditText.

@Override
    public InputConnection onCreateInputConnection(@NonNull EditorInfo outAttrs) {
        InputConnection connection = super.onCreateInputConnection(outAttrs);
        int imeActions = outAttrs.imeOptions&EditorInfo.IME_MASK_ACTION;
        if ((imeActions&EditorInfo.IME_ACTION_DONE) != 0) {
            // clear the existing action
            outAttrs.imeOptions ^= imeActions;
            // set the DONE action
            outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE;
        }
        if ((outAttrs.imeOptions&EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
            outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
        }
        return connection;
    }

You can also set which EditTexts should gain focus next in your layout with

android:nextFocusDown=""

passing in the id of the EditText you want to be focused next.

Upvotes: 1

Related Questions