Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: how to capture long press event on soft input/keyboard?

Short version of question: how can I capture long press event on soft input/keyboard in Android?

Long version: In an Android app, we have a multi-line EditText, and we want to have this behavior: 1. By default, it's showing a DONE button, by tapping it, soft input/keyboard will be closed. 2. If user long press the DONE button, its behavior will be changed to ENTER button, and there will have a new line in the EditText.

For requirement #1, I used the solution in here: https://stackoverflow.com/a/12570003/4225326

For requirement #2, the blocking question I have is, how to capture the long press event. I set the onEditorActionListener, but the captured event is null: http://developer.android.com/reference/android/widget/TextView.OnEditorActionListener.html I searched the document, the long press related method is for hard keyboard: http://developer.android.com/reference/android/view/View.html#onKeyLongPress(int, android.view.KeyEvent), I can't find one for soft input/keyboard.

Thanks for looking into this question.

like image 616
Samuel Cai Avatar asked Dec 12 '14 02:12

Samuel Cai


People also ask

How does Android handle keyboard events?

To handle an individual key press, implement onKeyDown() or onKeyUp() as appropriate. Usually, you should use onKeyUp() if you want to be sure that you receive only one event. If the user presses and holds the button, then onKeyDown() is called multiple times.

How do I make the keyboard softer on my Android?

To show the input method when your activity starts, add the android:windowSoftInputMode attribute to the <activity> element with the "stateVisible" value. For example: <application ... > Note: If the user's device has an attached hardware keyboard, the soft input method does not appear.

How do I prevent the soft keyboard from pushing my view up in fragment?

Setting android:isScrollContainer = "false" inside the ScrollView worked for me. According to the documentation, settings "isScrollContainer" to true means that the scroll view can be resized to shrink its overall window so that there is space for an input method.


1 Answers

I could not find this answer myself, so I manually coded the solution. I used a timer on the onPress() and onRelease() events of the KeyboardView.OnKeyboardActionListener. Here's the important code. Many TRY/CATCHes left out for brevity. In English, when a key is pressed, I'm starting a timer that waits the same time as a long-click event normally waits (ViewConfiguration.getLongPressTimeout()), then executes an on-long-click event on the original thread. Subsequent key releases and key presses can cancel any active timer.

public class MyIME
    extends InputMethodService
    implements KeyboardView.OnKeyboardActionListener {
    :
    :
    private Timer timerLongPress  = null;
    :
    :

    @Override
    public void onCreate() {
        super.onCreate();
        :
        :
        timerLongPress = new Timer();
        :
        :
    }

    @Override
    public void onRelease(final int primaryCode) {
        :
        :
        timerLongPress.cancel();
        :
        :
    }

    @Override
    public void onPress(final int primaryCode) {
        :
        :
        timerLongPress.cancel();
        :
        :
        timerLongPress = new Timer();

        timerLongPress.schedule(new TimerTask() {

            @Override
            public void run() {

                try {

                    Handler uiHandler = new Handler(Looper.getMainLooper());

                    Runnable runnable = new Runnable() {

                        @Override
                        public void run() {

                            try {

                                MyIME.this.onKeyLongPress(primaryCode);

                            } catch (Exception e) {
                                Log.e(MyIME.class.getSimpleName(), "uiHandler.run: " + e.getMessage(), e);
                            }

                        }
                    };

                    uiHandler.post(runnable);

                } catch (Exception e) {
                    Log.e(MyIME.class.getSimpleName(), "Timer.run: " + e.getMessage(), e);
                }
            }

        }, ViewConfiguration.getLongPressTimeout());
        :
        :
    }

    public void onKeyLongPress(int keyCode) {
        // Process long-click here
    }
like image 123
CrazyIvan1974 Avatar answered Sep 27 '22 16:09

CrazyIvan1974