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

2

12

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://mcmap.net/q/65745/-multiline-edittext-with-done-softinput-action-label-on-2-3

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.

Whencesoever answered 12/12, 2014 at 2:23 Comment(1)
Have you tried to add a doneButton.setOnLongClickListener(new OnLongClickListener() {...});Conciliatory
C
1

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
    }
Cholinesterase answered 24/10, 2016 at 19:43 Comment(3)
I am not so sure your solution will work as intended. According to the documentation, onPress() is called before onKey() once and onRelease is called after onKey(). This would mean, that onKey is going to be executed no matter what. If your solution is implemented then for the long press, both the key's normal behaviour and long press behaviour will be executed.Nickienicklaus
Another issue I can visualize is - "where do I set and how do I retrieve the long press key code?". This will be specially troublesome as the structure in the xml does not provide for such scenarios. Any comments?Nickienicklaus
this seems to work! the only issue is that it doesn't cancel what the key does on a short press, which is sent on key release. fixed this by returning true in the class that overrides KeyboardView.Practicable
P
-1

Create a custom Keyboard View class by extending the KeyboardView class. Override the onLongPress() method

Poulterer answered 22/4, 2018 at 19:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.