Как libgdx определяет наличие клавиатуры

При вводе текста в текстовое поле мне нужно, чтобы мое текстовое поле двигалось вверх, чтобы текстовое поле было видно при появлении клавиатуры.

Есть ли у libgdx какой-то метод, который возвращает истину, если клавиатура видна, и ложь, когда она не работает?


person Patrick Romstad    schedule 07.03.2012    source источник
comment
возможный дубликат Определить, отображается ли на экране программная клавиатура   -  person Shivan Dragon    schedule 07.03.2012
comment
Это не имеет ничего общего с libgdx, вы хотите прослушивать собственное событие Android. На этот вопрос был задан и дан ответ   -  person Shivan Dragon    schedule 07.03.2012
comment
Вроде, но если это не предусмотрено LibGDX, усилия по реализации для прослушивания этого события намного больше;).   -  person Dominik Bucher    schedule 07.03.2012


Ответы (3)


Следующий код обнаруживает, когда вы нажимаете текстовое поле, предотвращает отображение клавиатуры, а затем открывает собственный диалог, который перемещается вверх и вниз с помощью клавиатуры. Он примет ввод из собственного диалогового окна и, наконец, вернет его в ваше текстовое поле:

    textField.setOnscreenKeyboard(new TextField.OnscreenKeyboard() {
        @Override
        public void show(boolean visible) {
            //Gdx.input.setOnscreenKeyboardVisible(true);
            Gdx.input.getTextInput(new Input.TextInputListener() {
                @Override
                public void input(String text) {
                    textField.setText(text);
                }

                @Override
                public void canceled() {
                    System.out.println("Cancelled.");
                }
            }, "Title", "Default text...");
        }
    });

Удачи!

person JohnyTex    schedule 12.04.2014
comment
Есть идеи, как изменить стиль этого собственного диалога? - person Oliver Dixon; 19.05.2015
comment
Нет. Думаю, вы не можете этого сделать, потому что это будет отличаться для Android и iPhone, для настольных компьютеров Java и т. Д. Вкратце: его родной = ›Он работает изначально! - person JohnyTex; 19.05.2015

Я знаю, что отвечаю на старую ветку, но искал в Google ответ на этот вопрос, но нигде не нашел. Теперь я сам создал решение. Вот как это элегантно сделать на Android :) Я создаю ApplicationBundle для объединения интерфейсов и добавления специфичных для платформы вещей. Вы можете сделать это и на iOS, если хотите использовать RoboVM.

Мое решение:

создайте интерфейс SizeChangeListener в основном проекте:

public interface SizeChangeListener {
    public void onSizeChange(float width, float height);
}

создать интерфейс просмотра в основном проекте:

public interface View {
    public void onSizeChange(float width, float height);
    public void addListener(SizeChangeListener sizeChangeListener);
    public float getWidth();
    public float getHeight();
}

создать AndroidView, реализующий интерфейс View:

public class AndroidView implements View {

    private ArrayList<SizeChangeListener> listeners = new ArrayList<SizeChangeListener>();
    private float width, height;
    public AndroidView(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public void addListener(SizeChangeListener listener) {
        listeners.add(listener);
    }

    public void onSizeChange(float width, float height) {
        this.width = width;
        this.height = height;
        for(SizeChangeListener listener : listeners)
            listener.onSizeChange(width, height);
    }

    public float getWidth() {
        return width;
    }

    public float getHeight() {
        return height;
    }

}

создать ApplicationBundle в основном проекте

public class ApplicationBundle {

    private final View view;

    public ApplicationBundle(View view) {
        this.view = view;
    }

    public View getView() {
        return view;
    }
}

Сделайте необходимый импорт из основного проекта. В AndroidLauncher в проекте Android добавьте следующее:

public class AndroidLauncher extends AndroidApplication {

    private View rootView;
    private AndroidView androidView;
    private int width, height;

    @Override
    protected void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
        rootView = this.getWindow().getDecorView().getRootView();
        Rect rect = new Rect();
        rootView.getWindowVisibleDisplayFrame(rect);
        width = rect.width();
        height = rect.height();
        androidView = new AndroidView(width, height);

        rootView.addOnLayoutChangeListener(new OnLayoutChangeListener() {

            @Override
            public void onLayoutChange(View v, int left, int top, int right,
                    int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {

                Rect rect = new Rect();
                rootView.getWindowVisibleDisplayFrame(rect);

                if(!(width == rect.width() && height == rect.height())) {
                    width = rect.width();
                    height = rect.height();
                    androidView.onSizeChange(width, height);
                }
            }

        }); 

        initialize(new DigMeApp(new ApplicationBundle(androidView)), config);
    }
}

В вашем основном MyApp в основном проекте в методе create () добавьте реализацию SizeChangeListener в представление, которое вы получили из конструктора.

public class MyApp extends Game { // or ApplicationAdapter
    private View view;
    private Stage stage;
    // your own variables

    public MyApp(ApplicationBundle applicationBundle) {
        view = applicationBundle.getView();
    }

    @Override
    public void create () {
        stage = new Stage();
        // add some textfields
    final TextField tf1 = new TextField("", skin);
    final TextField tf2 = new TextField("", skin);

    tf1.setWidth((float)view.getWidth() * 0.6f);
    tf2.setWidth((float)view.getWidth() * 0.6f);
    tf1.setHeight((float)view.getHeight() * 0.05f);
    tf2.setHeight((float)view.getHeight() * 0.05f);
        view.addListener(new SizeChangeListener() {         
            @Override
            public void onSizeChange(float width, float height) {
                Gdx.app.log("INFO", "Visible area: " + width + "   " + height);
                Gdx.app.log("INFO", "Stage area: " + stage.getWidth() + "   " + stage.getHeight());
                float keyboardHeight = getKeyboardHeight();

// MOVE THEM OUT OF THE WAY :)

                tf1.addAction(Actions.moveTo(width / 2 - tf1.getWidth() / 2.0f, keyboardHeight + (6 * (height / 8)), 1, Interpolation.sineOut));
                tf2.addAction(Actions.moveTo(width / 2 - tf2.getWidth() / 2.0f, keyboardHeight + (7 * (height / 8)), 1, Interpolation.sineOut));


//              Gdx.gl20.
//              tf.setPosition(width / 2 - (tf.getWidth() / 2.0f), 0);
            }
        });
}

Возможно, создайте небольшой метод высоты клавиатуры, как я:

private float getKeyboardHeight() {
        return stage.getHeight() - view.getHeight();
    }
person Willempie    schedule 17.10.2015
comment
Мне нравится этот ответ, он очень хорошо работает на всех устройствах, на которых я его тестировал. Единственное замечание, которое я хотел бы сделать, это view.getHeight() необходимо масштабировать, чтобы соответствовать размерам сцены или камеры, если вы установили libgdx для определенного разрешения. @Willempie у вас есть рабочее решение для iOS? - person hamham; 25.05.2016
comment
Это отличный ответ, работает очень хорошо, и, к счастью, мне не нужно реализовывать способ iOS, так что это не проблема. Это должен быть выбранный ответ, хотя у меня есть один нюанс. Когда я касаюсь текстового поля, появляется клавиатура, появляется черный баннер в верхней части моего приложения с моим именем приложения в нем. Кажется, до линии rootView = this.getWindow().getDecorView().getRootView(); есть идеи, как этого избежать? - person Russ Wheeler; 16.02.2017
comment
[Решено] this.requestWindowFeature(Window.FEATURE_NO_TITLE); Я добавил эту строку до установки rootView - person Russ Wheeler; 16.02.2017
comment
Несмотря на то, что я собираюсь использовать этот метод в своей игре, примерно 1 раз из 10/20, новый размер не определяется, и я понятия не имею, почему. Не могу воспроизвести это кажется почти случайным :( - person Russ Wheeler; 17.02.2017
comment
Хорошее решение, жаль, что требуется Min API Level 11 - person Mitrakov Artem; 01.03.2017

Пытаться

Gdx.input.isPeripheralAvailable(Input.Peripheral.OnscreenKeyboard);

Я только что просмотрел это в документации, не знаю, действительно ли это помогает. Но

Gdx.input.setOnscreenKeyboardVisible(boolean visible);

также может быть использован метод (например, ВЫ определяете, когда клавиатура видна, а когда нет).

person Dominik Bucher    schedule 07.03.2012
comment
Пробовали Input.Peripheral.OnscreenKeyboard, но это всегда верно при запуске приложения на android. Но попробую вручную сделать, спасибо за подсказку :) - person Patrick Romstad; 07.03.2012
comment
В противном случае, как предложил Андрей Боднареску, вы всегда можете прослушивать события, как описано в stackoverflow.com/questions/4745988/, используйте ту же структуру, что и я описал в stackoverflow.com/questions/9584959/. Ваше здоровье! - person Dominik Bucher; 08.03.2012
comment
Кажется, что возврат всегда правда нет? - person JohnyTex; 11.04.2014