Как отключить автозаполнение / предложить при использовании InputMethodManager.showSoftKeyboard () - PullRequest
1 голос
/ 05 ноября 2019

Попытка исправить ошибку в моем приложении LibGDX, когда некоторые пользователи Android сообщают, что пробел вставляет слова «автозаполнения» в свой ввод. В некоторых случаях программная клавиатура даже не отображает предложения автозаполнения.

Насколько я понимаю, LibGDX не использует "нативные" элементы пользовательского интерфейса Android, поэтому объект TextField запускает этот код при нажатии:

public void setOnscreenKeyboardVisible (final boolean visible) {
        handle.post(new Runnable() {
            public void run () {
                InputMethodManager manager = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
                if (visible) {
                    View view = ((AndroidGraphics)app.getGraphics()).getView();
                    view.setFocusable(true);
                    view.setFocusableInTouchMode(true);
                    manager.showSoftInput(view, 0);
                } else {
                    manager.hideSoftInputFromWindow(((AndroidGraphics)app.getGraphics()).getView().getWindowToken(), 0);
                }
            }
        });
    }

Итак, вот эта строка, которая показывает клавиатуру:

manager.showSoftInput(view, 0);

Как мне установить некоторые флаги или что-то, чтобы сказать клавиатуре отключить автозаполнение?

Примечание, это происходит только с некоторыми пользователями, не могут найти шаблон. Кроме того, пока только для Android 8 и 9.

1 Ответ

0 голосов
/ 08 ноября 2019

Я немного искал, и оказалось, что это совсем не просто.

В показанном вами методе AndroidInput для отображения клавиатуры используется представление app.getGraphics().getView(). Как объяснено в другом ответе , вам нужно будет создать подкласс этого представления и переопределить следующий метод, чтобы иметь возможность установить флаги ввода:

@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    InputConnection connection =  super.onCreateInputConnection(outAttrs);
    // Set flags to disable suggestions. Visible password flag is only needed for some devices.
    outAttrs.inputType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS 
            | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
    return connection;
}

За исключением представления, используемого AndroidGraphicsне особенно легко подкласс. Вместо этого вы можете создать подкласс класса AndroidInput и предоставить другое представление для ввода. Вот пример класса запуска:

class AndroidLauncher extends AndroidApplication {

    private View inputView;
    private Handler handle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Config and init your game class.
        AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
        initialize(new MyGame(), config);

        // Custom view used for showing the keyboard.
        // Most of the code in onCreateInputConnection comes from the GLSurfaceView20 class.
        inputView = new View(this) {
            @Override
            public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
                if (outAttrs != null) {
                    outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI;
                    // This line is the only different from original source, it disables suggestions.
                    outAttrs.inputType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
                            | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
                }

                return new BaseInputConnection(this, false) {
                    @Override
                    public boolean deleteSurroundingText (int beforeLength, int afterLength) {
                        int sdkVersion = android.os.Build.VERSION.SDK_INT;
                        if (sdkVersion >= 16) {
                            if (beforeLength == 1 && afterLength == 0) {
                                sendDownUpKeyEventForBackwardCompatibility(KeyEvent.KEYCODE_DEL);
                                return true;
                            }
                        }
                        return super.deleteSurroundingText(beforeLength, afterLength);
                    }

                    @TargetApi(16)
                    private void sendDownUpKeyEventForBackwardCompatibility (final int code) {
                        final long eventTime = SystemClock.uptimeMillis();
                        super.sendKeyEvent(new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, code, 0, 0,
                                KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
                        super.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime, KeyEvent.ACTION_UP, code, 0, 0,
                                KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
                    }
                };
            }
        };
        handle = new Handler();  // handle is private in AndroidInput so we create our own.

        // Android has two different AndroidInput classes depending on SDK versions, create the right one. You can remove one of them if you don't support API < 12.
        if (Build.VERSION.PREVIEW_SDK_INT >= 12) {
           input = new AndroidInputThreePlus(this, this, graphics.getView(), config) {
               @Override
               public void setOnscreenKeyboardVisible(boolean visible) {
                   AndroidLauncher.this.setOnscreenKeyboardVisible(visible);
               }
           };
        } else {
            input = new AndroidInput(this, this, graphics.getView(), config) {
                @Override
                public void setOnscreenKeyboardVisible(boolean visible) {
                    AndroidLauncher.this.setOnscreenKeyboardVisible(visible);
                }
            };
        }
    }

    private void setOnscreenKeyboardVisible(final boolean visible) {
        // Code comes from AndroidInput.setOnscreenKeyboardVisible except view is changed.
        handle.post(new Runnable() {
            public void run () {
                InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                if (visible) {
                    inputView.setFocusable(true);
                    inputView.setFocusableInTouchMode(true);
                    manager.showSoftInput(inputView, 0);
                } else {
                    manager.hideSoftInputFromWindow(inputView.getWindowToken(), 0);
                }
            }
        });
    }
}

Так что, как вы можете видеть, это не совсем легко сделать. Я тоже не проверял, так что, может быть, мне больше чего-то не хватает.

В этот момент я бы скорее предложил вам подать проблему на github и сделать запрос на получение. Реализация графического представления для Android - GLSurfaceView20 (или GLSurfaceView20API18), и она уже переопределяет onCreateInputConnection. Вы можете добавить опцию, чтобы отключить предложения в интерфейсе Input и внедрить ее на каждом бэкэнде.

Если у вас есть какие-либо вопросы по этому поводу, не стесняйтесь спрашивать.

...