Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do libgdx detect keyboard presence

Tags:

android

libgdx

When writing in the Textfield, I need my textfield to move upwards in order to let the textfield be visible when the keyboard pops up.

Does libgdx have some kind of method which returns true if the keyboard is visible and false when it is down?

like image 401
Patrick Romstad Avatar asked Mar 07 '12 16:03

Patrick Romstad


3 Answers

The following code will detect when you press a textfield, prevent it from showing the keyboard and then open a native dialog that moves up and down with the keyboard. It will take the input from the native dialog and finally put it back in your textField:

    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...");
        }
    });

Good Luck!

like image 111
JohnyTex Avatar answered Nov 12 '22 14:11

JohnyTex


I know I'm answering to an old thread, but I was googling to find an answer to this question but couldn't find it anywhere. Now I have created a solution myself. Here is how to do it on Android in an elegant way :) I'm creating an ApplicationBundle to bundle interfaces to add platform specific things. You can do this on iOS too if you want to make use of RoboVM.

My solution:

create a SizeChangeListener interface in the core project:

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

create a View interface in the core project:

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

create an AndroidView implementing the View interface:

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;
    }

}

create an ApplicationBundle in the core project

public class ApplicationBundle {

    private final View view;

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

    public View getView() {
        return view;
    }
}

Make the necessary imports from the core project. In the AndroidLauncher in the Android project add the following:

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);
    }
}

In your main MyApp in the core project in the create() method add a SizeChangeListener implementation to the view you've got from the constructor.

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);
            }
        });
}

Perhaps create a little keyboard heigt method like I did:

private float getKeyboardHeight() {
        return stage.getHeight() - view.getHeight();
    }
like image 7
Willempie Avatar answered Nov 12 '22 14:11

Willempie


Try

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

I just looked this up in the docs, don't know if it actually does the trick. But the

Gdx.input.setOnscreenKeyboardVisible(boolean visible);

method could be used as well (like this YOU define when the keyboard is visible and when not).

like image 2
Dominik Bucher Avatar answered Nov 12 '22 13:11

Dominik Bucher