Nifty TextField on Android (46 posts)

  • Profile picture of iwgeric iwgeric58p said 3 months, 1 week ago:

    I’ve been expanding Nifty’s role in my Android app. I’ve got a checkbox, button, and text to work, but I’m having an issue with TextField. I’d like to have the ability for the user to enter a number into a text box to change a game setting. The textfield display ok and when I touch the textfield and the blinking cursor shows up, but the Android keyboard does not appear so the user cannot enter any text.

    Has anyone been able to display the Android keyboard when the user touches a TextField? I’d really not like to create my own keypad in Nifty to allow for data entry.

  • Profile picture of nehon nehon590p said 3 months, 1 week ago:

    Well nifty textField is not really a text fields for android….
    isn’t there a way to manually pop the keyboard? surely there is
    I mean in the android API?
    Maybe we should ad some API to do this from the harness or something….

    For now what you could do is to create some kind of PopKeyBoardListener on the android side of the project, and make your nifty controller notify this listener when the field gets the focus…

  • Profile picture of iwgeric iwgeric58p said 3 months, 1 week ago:

    That’s exactly what I’m working on now. I’ve got my nifty controller being notified when the text field gains and loses focus and a listener setup to notify MainActivity. Next I’ll display the soft keyboard and see if jme sees the keys and forwards them to nifty. I’ll keep you posted.

  • Profile picture of nehon nehon590p said 3 months, 1 week ago:

    @iwgeric said:
    and see if jme sees the keys and forwards them to nifty.

    uh right I didn’t think of this….it could be an issue…if it does not works you may have to add Action listeners to grab keyboard events…
    There is a setSimulateKeyboard() on the jme’s glSurfaceView, it sets a keyboardEventsEnabled boolean…but i’m afraid it’s never used…so no magic :p

    I’m looking forward your tests results.

  • Profile picture of nehon nehon590p said 3 months, 1 week ago:

    also there is a ANDROID_TO_JME static array that looks like a map from JME’s keyInputs to android’s keyInputs but it’s also never used ….I guess it’s still a work in progress….and since there no official android guy in the team anymore….I guess i’ll add it to my todo :p

  • Profile picture of iwgeric iwgeric58p said 3 months, 1 week ago:

    @nehon said:
    I’m looking forward your tests results.

    I’m having some issues figuring out how to get the soft keyboard to display. I thought the following would work, but it isn’t.

     InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
    

    I’ll keeping looking into it, but if you know how to get the keyboard to display, let me know.

  • Profile picture of iwgeric iwgeric58p said 3 months, 1 week ago:

    The more I look into this, the less sure I am that an Android soft keyboard is the right way to go.

    Q1) Would it be better to have the keyboard created and displayed via Nifty?

    This way, it would work on any of the platforms supported by the platform. However, I think it might be tricky creating a keyboard in Nifty. Mainly, to support various screen sizes, I think the letters would need to be scaled to fit the keyboard on smaller screens. I know that the layout, panels, and buttons can be scaled based on % instead of px, but I don’t know if the letters can be scaled.

    Q2) Is there a way to scale the letters displayed on a Nifty button or do you have to have different Fonts at different sizes in order to change the text size of the labels?

  • Profile picture of nehon nehon590p said 3 months, 1 week ago:

    1/ erf sounds hardcore :p
    seen this post? http://stackoverflow.com/questions/2479504/forcing-the-soft-keyboard-open/6977565#6977565
    I didn’t test it but the guy sounds pretty confident that it works
    EDIT : nvm looks like it’s what you tested….

    2/Afaik you can’t scale text, you have to create different size fonts.

  • Profile picture of iwgeric iwgeric58p said 3 months, 1 week ago:

    Well, I got the keyboard to open and notify my MainActivity what the text is after each letter is pressed. The bad news is I could only figure out how to do it when a EditText has the focus. I put an EditText behind the GLSurfaceView so it isn’t visible and to a editText.requestFocus() and then do the code to open the keyboard. If I make the EditText invisible or try to use the GLSurfaceView, the keyboard doesn’t open.

  • Profile picture of iwgeric iwgeric58p said 3 months, 1 week ago:

    OK, I think I have something that will work. I’m using the KeyboardView widget in Android. This allows you to define an XML file to layout the keys and an interface to receive the keycodes that correspond to the button/key pressed. I think with this users can use a default key layout that we provide as well as redefine their own XML file that includes the keys that want to display. It also scales itself based on the orientation and screensize of the device and allows for images or characters to be placed on the keys.

    Currently, when I touch a textfield in Nifty, the EventBus subscription calls a routine on the android side which displays the keyboardview. When I touch the ENTER key on the keyboardview, the keyboardview dismisses and focus is returned to Nifty.

    I’m going to move the android side of the code into AndroidHarness instead of MainActivity and then try to figure out how to map the keycodes from Android into ones that Nifty wants. Maybe I can use the Android_to_JME mappings to do this.

    Still a ways to go to get something usable, but its a start. Let me know if you think this way would be acceptable.

  • Profile picture of nehon nehon590p said 3 months, 1 week ago:

    i don’t get what’s the KeyboardView widget is, it’s a nifty control?

    Will it support different keyboard layouts? (qwerty, azerty, and everything else)

    Anyway thank you for your efforts it’s really appreciated.

  • Profile picture of iwgeric iwgeric58p said 3 months ago:

    A KeyboardView is an Android View that reads an XML file to determine what keys to show (images or characters) and what keycodes to return when the user clicks on a key.
    http://developer.android.com/reference/android/inputmethodservice/KeyboardView.html
    It would be a matter of changing the XML file to display different keyboards like a numeric keypad, querty keypad, etc… I haven’t decided yet whether to pass each key to Nifty individually or wait until the user dismisses the keypad and then pass the entire string to Nifty. It will depend, I think, on whether or not passing a keycode for “backspace” will work when passed to Nifty. I image that passing a backspace to nifty will delete the previous character in the Nifty control, so if that works, I’ll probably pass each character individually back to Nifty.

    Another thing to figure out is how to tell the Android View which keyboard to use (which XML file to read) when the user activates various Nifty controls. I think it will require different NiftyEventSubscribers that pass an XML filename back to AndroidHarness or a predefined constant that reads a specific XML file. Not sure yet.

    The nice thing about the KeyboardView is that it handles all the click events and passes back the key string and keycode so that we can convert the keycode for Nifty.

  • Profile picture of nehon nehon590p said 3 months ago:

    sounds good to me!
    nice found.

  • Profile picture of iwgeric iwgeric58p said 3 months ago:

    Well, I found that implementing the KeyboardView was going to be much more work than I thought it was worth. After taking a step back, I decided to implement something else entirely. Maybe it’s just lazyness, but to do it right, I would have needed to implement a whole Input Manager for the keyboard which I didn’t think was worth it.

    Instead, I implemented a way for the engine to fire off an event that would start up an alert box on the android side for the user to type in whatever they want with the default Android keyboard. Once the alert box text entry is complete, the entire string is then returned to the caller so that they can do whatever they want with the text.

    I have this working with Nifty textfields. Basically, when the text is returned to my screen controller, I then take the text and set the textfield text. I think this is probably better for a couple of reasons:
    1. Users will use whatever keyboard they have defined
    2. Every individual key code does not need to be implemented in JME since it just uses the resulting string
    3. Future chat style implementations can also use this method to create strings to send over the network

    Anyway, I’ll need another day or 2 to create the patch files, but the general changes are in:

    AndroidHarness – creates the dialog box and returns the resulting text
    SoftTextDialogInput – new interface for the engine to call to start the dialog box. This is currently located in package com.jme3.input so that it can be used for other platforms in the future (ie. iPhone, etc)
    SoftTextDialogInputListener – new interface to send back the completed text
    InputManager – added setters and getters for the SoftTextDialogInput class to use to create the dialog
    AndroidInput – sets the SoftTextDialogInput in InputManager to AndroidHarness. Other platforms would set variable in InputManager to thier own implementations in their own contexts

    As I said, I have it all working in a modified version of the engine. The user implentation is the following:
    In the Nifty XML file, I have an onClick interaction defined to call a routine in the Screen Controller. In the Screen Controller, I have the following:

        public void changeGravity() {
            logger.log(Level.INFO,"changeGravity");
    
            TextField textField = screen.findNiftyControl("txtGravity", TextField.class);
            String initialValue = "";
    
            if (textField != null) {
                initialValue = textField.getText();
            } else {
                logger.log(Level.INFO, "textField is null getting initial value");
            }
    
            SoftTextDialogInput softTextDialogInput = app.getInputManager().getSoftTextDialogInput();
            if (softTextDialogInput != null) {
                logger.log(Level.INFO, "Requesting soft dialog input");
                softTextDialogInput.requestDialog(SoftTextDialogInput.NUMERIC_ENTRY_DIALOG, "Gravity", initialValue, new SoftTextDialogInputListener() {
    
                    public void onSoftText(int action, String text) {
                        logger.log(Level.INFO, "onTextDialogDismissed: action: {0}, text: {1}",
                                new Object[]{action, text});
                        if (action == SoftTextDialogInputListener.COMPLETE) {
                            TextField textField = screen.findNiftyControl("txtGravity", TextField.class);
                            if (textField != null) {
                                textField.setText(text);
                            } else {
                                logger.log(Level.INFO, "textField is null in Results Listener");
                            }
                        }
                    }
                });
            } else {
                logger.log(Level.INFO, "softTextDialogInput is null");
            }
        }
    

    The above calls the Dialog creation interface and takes the returned text string and sets the TextField back in Nifty. No other user code is necessary.

    @nehon I know it’s a lot to take in without playing with it, but let me know what you think.

    EDIT: In case you’re wondering, this doesn’t affect the PC version. If the PC version is being executed, SoftTextDialogInput in InputManager is null and the code is skipped and the PC keyboard still works to set the text in the textfield.

  • Profile picture of nehon nehon590p said 3 months ago:

    hehe sometimes you got to step back and do it allover again ;)

    That looks like a more robust solution as it’s the android soft keyboard that is triggered. Also the fact that you send the resulting string is clever, that avoid messing with the keyboard inputs.

    Only thing i’m not fond of is the SoftTextDialogInput in the input manager, even if it’s null, it’s useless on the desktop side of the engine…
    Can’t it be a AndroidInput attribute instead? Why do you need it to be in the InputManager?

    Anyway I like this solution better, nice work ;)