24

We are working on our first android app and it has been a very enjoyable experience so far. It is almost complete, but before release we are having some considerations ,mainly about android soft keyboard.

We have a couple of EditText fields that are used to enter numbers. We would like to capture the event when user presses enter, and do some calcuations and saving on this callback.

The problem is that we are not getting a fixed event as different phones have different keyboards. Some have 'Done' button and our HTC phones have 'Enter' buttons. We tried using the imeOptions as 'done' but that had no effect on the HTC phones.

We also know that the keyboard can be dismissed by hitting the back button. So my question is if there is a reliable way to know when the user has stopped entering or when the keyboard is hidden, just like textFieldShouldReturn callback in iphone sdk(which will always fire when keyboard goes down, independent of what key caused it to go down)..

In other words, how an android developer handles soft keyboard? I check for KeyEvent.KEYCODE_ENTER on editText onClick() event and do my tasks there.It is working on my HTC android, but not on my friends Nexus phone, which has a done button instead of enter. There onClick is not even called. How a developer handles this?

EDIT: After losing half of my hair, and with the help of some good friends here

I have tried all your suggestions but at the end by using onEditorActionListener along with onKeyListener method did the trick for me. In onEdit callback of onEditorActionListener I checked for KeyCode ACTION_DONE, which did get called on keyboards with done button. On keyboards which has enter onKey gets called. In onKey method I checked for KEYCODE_BACK also, so that hardware back press event also can be handled. I haven't yet found out a android device with done and enter on the keyboard (seriously), still I even handled that case with a flag. Thanks @Femi for suggesting onEditorActionListener, and thanks for all friends for your help. But the answer to my original question

Q: Is there an reliable and easier way to know android soft keyboard resigns (callback that works on every phone)

Ans : No, All methods suggested here and all methods suggested on other sites are not straightforward. And I think handling an event for keyboard return key is the most basic thing for any operating system. Google, are you there?

Krishnabhadra
  • 34,169
  • 30
  • 118
  • 167
  • How do you handle the hardware keyboard? I think the lack of a "done with the keyboard" event on Android may be due to the possible existence of an ever-present hardware keyboard. I wonder if your UI needs a re-think. Are your "calculations and saving" too expensive to do on every key press? – Martin Stone May 23 '11 at 18:48
  • Thanks for the reply @Martin, I have tested on devices with/without hardware keyboard, and didnt have any problem handling button click on hardware keyboard. – Krishnabhadra May 24 '11 at 03:17
  • " I think the lack of a "done with the keyboard" event on Android may be due to the possible existence of an ever-present hardware keyboard", well, Soft keyboard done event didn't get called on a device which didn't have hardware keyboard. – Krishnabhadra May 24 '11 at 03:20
  • 1
    What I meant was, Android may not provide such an event because it would be no use if your app was used without a soft keyboard. (And relying on it would lead to an unreliable app). – Martin Stone May 24 '11 at 19:14
  • Got your point @Martin. But they are providing a widget called EditText, which can take an input from hard or soft keyword. Why don't they implement a mechanism of callbacks which gets called irrespective of whether the keyboard is hard or soft.. – Krishnabhadra May 25 '11 at 03:45
  • mhh but with that solution you still don't know when the user closes the software keyboard by pressing the hardware back button, right? – jpm May 26 '11 at 21:00
  • Well @jpm, I fooled around with the original answer again, Now I am using onKeyListener on my editText instead of onClickListener. And I am getting onKey() callback when software keyboard enter press, and hardware back button. To handle done button, onEditorAction remains there. I have edited my answer (rather edit part of question). Still I am not proud of Android for the way they have handled soft keyboard. – Krishnabhadra May 27 '11 at 03:28
  • I am surprised that your solution works for you(it did not work for me) despite the warning at developer.android.com/reference/android/view/… : "Key presses in software keyboards will generally NOT trigger this method, although some may elect to do so in some situations. Do not assume a software input method has to be key-based; even if it is, it may use key presses in a different way than you expect, so there is no way to reliably catch soft input key presses." – faizal Dec 17 '13 at 17:11

7 Answers7

7

Since it seems that you are catching the KEYCODE_ENTER event, you might be able to use this: http://developer.android.com/reference/android/widget/TextView.html#setOnEditorActionListener%28android.widget.TextView.OnEditorActionListener%29. In theory this will let you detect whatever the input method end action is (whether its back, done, enter, or whatever) and respond to it.

Let me know if that works for you.

Femi
  • 64,273
  • 8
  • 118
  • 148
  • Is editorActionListener the common way used by every developer? I cant believe Google doesnt have a keyboard independant callback for this case. – Krishnabhadra May 09 '11 at 06:04
  • 1
    That particular action doesn't (oddly enough) appear to be heavily used: I've somehow never had to use it,but now that I hear about it does seem like it would be more standard. There is typically a **submit** or **OK** button, so that handles it: you'd HAVE to be done editing to hit the submit button, so you don't need to listen for the enter on the TextView. I'd worry about users hitting enter by accident or not being able to confirm their input. However, when you describe it, it does sound like it would be a neat UI interaction. – Femi May 09 '11 at 06:11
  • Can I use onConfigurationChanged here so that I can get a callback when keyboard resigns? – Krishnabhadra May 09 '11 at 12:16
  • http://stackoverflow.com/questions/456211/activity-restart-on-rotation-android..this link tells about onConfigurationChanged.. – Krishnabhadra May 09 '11 at 12:16
  • Have you though about devices with physical keyboard? – neteinstein May 17 '11 at 12:52
  • Ya I tested on one device and emulator, and thankfully onClick function got called.. – Krishnabhadra May 17 '11 at 13:05
  • Please see the edit in my question..This answer didn't work alone (atleast for me). I have explained the procedure in my edit – Krishnabhadra May 24 '11 at 03:38
2

Wouldn't you also need to perform those calculations when the user is leaving the TextView on a hardware keyboard? I wouldn't focus on the keyboard, but on the TextView itself. If so, what you probably want is setTransformationMethod

You'd have to implement a custom TransformationMethod, specifically the method getTransformation, which transforms a source CharSequence into another one. You can then use the onFocusChanged to apply this only when the focus is lost for that TextView.

M Granja
  • 845
  • 8
  • 26
  • "I wouldn't focus on the keyboard, but on the TextView itself" , right thinking and it is the way I am familiar with in iphone(textFieldShouldReturn). But the thing is, My phone has a hardware keyword, And when I click on the enter button there, onClick is getting called. Until now, I didnt have any problem handling hardware keyboard. – Krishnabhadra May 24 '11 at 03:21
1

I cant believe Google doesnt have a keyboard independant callback for this case

Wow, I cant believe that neither. I am having a similar problem at the moment. In addition to the IME ACTION I check for focus changes on the EditFields. This is fine for most of the time, but won't work always.

I found a way to be notified when the keyboard is being hidden, but it's not a complete solution yet (and I'm not sure whether it's a good idea), but I don't have the time to continue right now, so I thought I can drop the start of the idea here...:

Write your own EditText(extend EditText) and override onCreateInputConnection. In your onCreateInputConnection return your own implementation of InputConnection (you can simply extend BasicInputConnection. The InputConnections "finishComposingText()" method is always called when the keyboard is being hidden (also when the user presses the back-key).

This is the code, and maybe someone else has an idea, why the entered text is not shown in this editfield ;-)

public class MyEditText extends EditText{

public MyEditText(Context context) {
    super(context);
}

public MyEditText(Context context, AttributeSet attrs) {
    super(context);
}

public MyEditText(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    System.out.println("onCreateInputConnection, "+outAttrs.actionId);
    return new MyInputConnection(this,true);
}

private class MyInputConnection extends BaseInputConnection{

    public MyInputConnection(View targetView, boolean fullEditor) {
        super(targetView, fullEditor);
    }

    @Override
    public boolean finishComposingText() {
        System.out.println("FINISH");
        return super.finishComposingText();
    }   
}
 }

JPM

James Goodwin
  • 7,360
  • 5
  • 29
  • 41
jpm
  • 3,300
  • 1
  • 19
  • 29
  • well,@jpm, thanks for the reply..some food for thought you have given here..Surely going to try this...Still I feel as if I am touching my nose around my head..:( – Krishnabhadra May 19 '11 at 08:29
  • And my main question is "how an android developer handles soft keyboard?"..What is the preferred way?..Anyone in SO who have an android app which uses soft keyboard? – Krishnabhadra May 19 '11 at 08:37
1

I found a solution on this SO page: Intercept back button from soft keyboard

The answer from mhradek has 0 votes but it seems to be working.

The idea is to extend the base layout of your activity so that you can override the dispatchKeyEventPreIme method and do what you want regarding the KeyEvent passed. Note that you are responsible for managing the soft keyboard.

I am using it and I can definitely intercept key strokes (the back button for example) without the soft keyboard "eating" them. I have yet to play more with it in order to see what is possible and what is not.

I hope it helps.

Community
  • 1
  • 1
Arnaud
  • 410
  • 5
  • 10
1

Have you tried implementing custom EditText view, where you override dispatchKeyEventPreIme? Just like in answer posted by Arnaud (referencing Intercept back button from soft keyboard) but instead of using custom layout use custom EditText and override:

@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
    if(KeyEvent.KEYCODE_BACK == event.getKeyCode()) {
       //this hides soft keyboard in super.dispatchKeyEventPreIme(event)
    }
    return super.dispatchKeyEventPreIme(event);
}

I suggested this solution in this question

Community
  • 1
  • 1
Ludevik
  • 6,954
  • 1
  • 41
  • 59
0

I have not tried this but, reading the documentation, it seems possible.

//    From an activity, you can call

if (getResources().getConfiguration().keyboardHidden == Configuration.KEYBOARDHIDDEN_YES) {
// your code here
}
Yogesh
  • 311
  • 1
  • 10
  • 1
    Rather than giving nearly identical answers, please _tailor_ your answers to each individual question that you choose to answer. Stack Overflow is for _high quality_ questions and answers, boilerplate answers are almost never the right approach. (Also, a citation or link to the specific documentation you read would be helpful in providing further details to questioners and future visitors.) For more advice, please read http://msmvps.com/blogs/jon_skeet/archive/2009/02/17/answering-technical-questions-helpfully.aspx – sarnold Jul 08 '11 at 09:39
0

This code is working fine for me with HTC and default Android keyboard:

editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                // handle enter key on keyboard
                if (actionId == EditorInfo.IME_ACTION_SEND || 
                        (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN)) {
                    if (uid != null) {
                        // hide keyboard
                        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
                        imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                        // perform other stuff

                        return true;
                    }
                }
                return false;
            }
        });

Using the following in the editText´s XML:

android:imeOptions="actionSend"

Of course you could also use something else like send, just make sure to change it in both the XML and Java code.

Konsumierer
  • 1,295
  • 1
  • 15
  • 33