Android Gets delete Event from Soft Keyboard

Keywords: Android Google emoji

For soft keyboard deletion events, there are many schemes on the web as follows, but google api also shows that this is just listening on the hardware keyboard and not triggering on the software keyboard (I tested that the soft keyboard can listen on the delete key, other keys like numeric letters do not trigger the listening method here).

editText.setOnKeyListener(new OnKeyListener() {                 
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        //You can identify which key pressed buy checking keyCode value with KeyEvent.KEYCODE_
        if(keyCode == KeyEvent.KEYCODE_DEL) {  
            //this is for backspace
        }
        return false;       
    }
});

Of course, there is also a TextWatcher that handles delete events, but this listening only triggers when the data changes. If edittext itself has no content, then clicking on the software disk delete key will not trigger the method here.

Similar to the following logic:

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    mPreviousLength = s.length();
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}

@Override
public void afterTextChanged(Editable s) {
    mBackSpace = mPreviousLength > s.length();

    if (mBackSpace) {

        // do your stuff ...

    } 
}


In fact, for the monitoring of software disks, but also from the source, here first describes the custom view input

Android Custom View to receive input from Input Method

This article is from: http://www.jianshu.com/p/2b483febec72

From this article, you can learn how event mechanisms of input methods work, and similar principles apply to official edittext s.

For many new people, only EditText and TextView controls can accept input from input method. In fact, they can accept input from input method as long as they are a subclass of View.

Now let's do it step by step, the first step is to have a subclass of View.

//First we have to override one of the methods in the View, returning true, which is to make the View editable with text, and returning false by default. 
@Override public boolean onCheckIsTextEditor() { 
    return true; 
    } 
    //The second is the override method, which returns an InputConnect object, which serves as a bridge to the input of the input method.
public InputConnection onCreateInputConnection(EditorInfo outAttrs);

// outAttrs is the type of input method that we need to set up. The most important thing is:
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI; outAttrs.inputType = InputType.TYPE_NULL;

I'm just setting it up here. The important thing is the InputConnect object that is returned.The following are
InputConnection 
Methods that need to be overridden

//Usually we are a subclass of BaseInputConnection, which implements the InputConnection interface.

//It is important to note that there are several ways to note rewriting.

@Override
public boolean commitText(CharSequence text, int newCursorPosition) { 
     Log.d("hickey", "commitText:" + text + "\t" + newCursorPosition);
     if (containsEmoji(text.toString())) { 
        Log.d("hickey", "send emoji"); 
        return true;
     } 
     if (mPlayer != null && mPlayFragment.isInputMethodStatus()) {
          Log.d("hickey", "text:" + text); 
          mPlayerView.sendCharEvent(text.toString());
     } 
    return true;
 }

note:This is when the input method enters characters, including emoticons, letters, text, numbers, and symbols.We can pass text Filter out what we don't want to display as custom view Above.

//There are text inputs and, of course, key inputs. Also note that some input methods do not transfer numbers by commitText, but instead use keys, such as KeyCode_1 for 1.

    @Override
    public boolean sendKeyEvent(KeyEvent event) {
        /** When the finger leaves the key */
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            Log.d("hickey", "sendKeyEvent:KeyCode=" + event.getKeyCode());
            if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
                mPlayerView.sendFunctionKeyCodeEvent(KeyEvent.KEYCODE_DEL);
            } else if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
                mPlayerView.sendFunctionKeyCodeEvent(KeyEvent.KEYCODE_ENTER);
                mPlayFragment.setInputMethodStatus(false, 1);
            } else {
                mPlayerView.sendCharKeyCodeEvent(event.getKeyCode());
            }
        }
        return true;
    }

note: Here I just delete, return key processing, because it triggers the action to press and release twice, so only press processing is done here.

//Of course deletion will also trigger
@Override
    public boolean deleteSurroundingText(int beforeLength, int afterLength) {
        Log.d("hickey", "deleteSurroundingText " + "beforeLength=" + beforeLength + " afterLength=" + afterLength);
        mPlayerView.sendFunctionKeyCodeEvent(KeyEvent.KEYCODE_DEL);
        return true;
    }

 @Override
    public boolean finishComposingText() {
        //When ending combined text input
        Log.d("hickey", "finishComposingText");
        return true;
    }
//This method will basically appear when you switch the input method type. Clicking Enter (Finish, Search, Send, Next) and clicking Hide button in the upper right corner of the input method will trigger.

//This raises a number of questions, such as what do we need to do when we click on View?
//InputMethodManager allows us to control how the input method pops up and retracts.

    InputMethodHelper(Context mContext) {
        inputMethodManager = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
    }

    public synchronized static InputMethodHelper getInstance(Context mContext) {
        synchronized (InputMethodHelper.class) {
            if (inputMethodHelper == null) {
                inputMethodHelper = new InputMethodHelper(mContext);
            }
            return inputMethodHelper;
        }
    }
    /**
     * Show Soft Keyboard
     *
     * @param view
     */
    public void showSoftInput(View view) {
        inputMethodManager.showSoftInput(view, 0);
    }

    /**
     * Hide Input Method
     */
    public void hideSoftInput(View view) {
        if (inputMethodManager.isActive()) {
            Log.d("hickey", "hideSoftInput:" + "hideSoftInputFromWindow");
            inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    }

//In a non-full-screen state, we can listen for popups and retracts of input methods by changing the layout size, but in a full-screen state, sorry, this is not possible at this time.For example, if a user clicks on the hidden button of an input method, the method finishComposingText will only be triggered, but it will also be triggered at other times, so it is not possible to listen for input method retraction by this method. InputMethodManager does not provide an API, so try to get the IMM's offer.

    public boolean isActive(View view){
        return inputMethodManager.isActive(view);
    }

    public boolean isActive(){
        return inputMethodManager.isActive();
    }

    public boolean isWatchingCursor (View view){
        return inputMethodManager.isWatchingCursor(view);
    }

    public boolean isAcceptingText(){
        return inputMethodManager.isAcceptingText();
    }

 

Nothing worked.

In another case, the current Activity exits, the input method is still in place, and there is nothing entered.Moreover, we have tried all methods of hiding input methods, which are not normal.

Here's a cheaper way to tell you. When the input method is alive, when we click the back button, it will hide the input method actively, and then click again to distribute the key events to the Activity.

So we need to simulate a return event.

new Thread(new Runnable() {
                @Override
                public void run() {
                    RedFinger.simulationEvent = true;
                    Instrumentation instrumentation = new Instrumentation();
                    instrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
                }
            }).start();


//Here's a bool flag to prevent input from being hidden and return key events from being distributed to the Activity, so you need to be on the page where you might exit



Looking at this, you can learn how to get the events of the soft keyboard.

There was also a lot of discussion on stackoverflow, and I found two articles

https://stackoverflow.com/questions/4886858/android-edittext-deletebackspace-key-event

https://stackoverflow.com/questions/18581636/android-cannot-capture-backspace-delete-press-in-soft-keyboard/34857618#34857618

A good solution has been found here, rewrite the edittext, code as follows

public class WiseEditText extends AppCompatEditText {  
  
  
    private OnKeyListener keyListener;  
  
    public WiseEditText(Context context, AttributeSet attrs, int defStyle) {  
        super(context, attrs, defStyle);  
    }  
  
    public WiseEditText(Context context, AttributeSet attrs) {  
        super(context, attrs);  
    }  
  
    public WiseEditText(Context context) {  
        super(context);  
    }  
  
    @Override  
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {  
        return new MyInputConnection(super.onCreateInputConnection(outAttrs),  
                true);  
    }  
  
    private class MyInputConnection extends InputConnectionWrapper {  
  
        public MyInputConnection(InputConnection target, boolean mutable) {  
            super(target, mutable);  
        }  
  
        @Override  
        public boolean sendKeyEvent(KeyEvent event) {  
            if (keyListener != null) {  
                keyListener.onKey(WiseEditText.this,event.getKeyCode(),event);  
            }  
            return super.sendKeyEvent(event);  
        }  
  
        @Override  
        public boolean deleteSurroundingText(int beforeLength, int afterLength) {         
            // magic: in latest Android, deleteSurroundingText(1, 0) will be called for backspace  
            if (beforeLength == 1 && afterLength == 0) {  
                // backspace  
                return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))  
                    && sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));  
            }  
  
            return super.deleteSurroundingText(beforeLength, afterLength);  
        }  
  
    }  
  
   //Set up listen callback  
    public void setSoftKeyListener(OnKeyListener listener){  
        keyListener = listener;  
    }  
  
}





   


        
    

Posted by spec36 on Fri, 07 Jun 2019 13:47:34 -0700