Rectangle 27 1

You could do it the other way, create an unique OnFocusChangedListener myListener and set it to all your EditTexts and put a switch inside and store which is the last view getting/losing focus

I thought of this, but the main problem is still knowing when the keyboard is about to be displayed. For example, focus could change (lose focus) because the keyboard gets displayed, OR focus could chance (lose focus) because another EditText was tapped.

I was gonna say check if keyboard is showing in the focuschanged but investigating a little, it's not as simple as might think: stackoverflow.com/questions/2150078/

Android: Detect When Soft Keyboard Is About to Show? - Stack Overflow

android keyboard android-edittext android-softkeyboard
Rectangle 27 142

I know a way to do this. Subclass the EditText and implement:

@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
  if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
    // Do your thing.
    return true;  // So it is not propagated.
  }
  return super.dispatchKeyEvent(event);
}

I am getting reports from Android users with Hardware keyboards that doing this somehow interferes with key presses. I don't have any additional info at this time.

I've been looking on several solution, this is by far the best!

Wait wait wait, I just looked at this a third time - shouldn't the super call be to onKeyPreIme? Or is there a particular reason for it not to be so?

Looks useful, except where the EditText can't be subclassed (e.g. in a SearchView). This is a problem when trying to hide the SearchView if empty when the keyboard is dismissed. I have to wonder why the android folks don't just provide some nice OSK APIs for this sort of thing.

SearchView

android - Detecting when user has dismissed the soft keyboard - Stack ...

android
Rectangle 27 142

I know a way to do this. Subclass the EditText and implement:

@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
  if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
    // Do your thing.
    return true;  // So it is not propagated.
  }
  return super.dispatchKeyEvent(event);
}

I am getting reports from Android users with Hardware keyboards that doing this somehow interferes with key presses. I don't have any additional info at this time.

I've been looking on several solution, this is by far the best!

Wait wait wait, I just looked at this a third time - shouldn't the super call be to onKeyPreIme? Or is there a particular reason for it not to be so?

Looks useful, except where the EditText can't be subclassed (e.g. in a SearchView). This is a problem when trying to hide the SearchView if empty when the keyboard is dismissed. I have to wonder why the android folks don't just provide some nice OSK APIs for this sort of thing.

SearchView

android - Detecting when user has dismissed the soft keyboard - Stack ...

android
Rectangle 27 106

public class EditTextBackEvent extends EditText {

    private EditTextImeBackListener mOnImeBack;

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

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

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

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && 
            event.getAction() == KeyEvent.ACTION_UP) {
            if (mOnImeBack != null) 
                mOnImeBack.onImeBack(this, this.getText().toString());
        }
        return super.dispatchKeyEvent(event);
    }

    public void setOnEditTextImeBackListener(EditTextImeBackListener listener) {
        mOnImeBack = listener;
    }

}

public interface EditTextImeBackListener {
    public abstract void onImeBack(EditTextBackEvent ctrl, String text);
}

@oliver_sdg sorry for the newbie question but how do I create the event handler for the EditText?

@CheokYanCheng it is because user action should normally take effect when releasing button, and not when starting to press it.

android.support.v7.widget.AppCompatEditText

Here, my friend Matias Maddonni does not have the reputation enough to comment and wants to thank you, @oliver_sdg, from the bottom of his heart because you saved his day. He says he will remember you and this day for the rest of his happy life :D

android - Detecting when user has dismissed the soft keyboard - Stack ...

android
Rectangle 27 106

public class EditTextBackEvent extends EditText {

    private EditTextImeBackListener mOnImeBack;

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

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

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

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && 
            event.getAction() == KeyEvent.ACTION_UP) {
            if (mOnImeBack != null) 
                mOnImeBack.onImeBack(this, this.getText().toString());
        }
        return super.dispatchKeyEvent(event);
    }

    public void setOnEditTextImeBackListener(EditTextImeBackListener listener) {
        mOnImeBack = listener;
    }

}

public interface EditTextImeBackListener {
    public abstract void onImeBack(EditTextBackEvent ctrl, String text);
}

@oliver_sdg sorry for the newbie question but how do I create the event handler for the EditText?

@CheokYanCheng it is because user action should normally take effect when releasing button, and not when starting to press it.

android.support.v7.widget.AppCompatEditText

Here, my friend Matias Maddonni does not have the reputation enough to comment and wants to thank you, @oliver_sdg, from the bottom of his heart because you saved his day. He says he will remember you and this day for the rest of his happy life :D

android - Detecting when user has dismissed the soft keyboard - Stack ...

android
Rectangle 27 13

Here is my custom EditText to detect whether keyboard is showing or not

/**
 * Created by TheFinestArtist on 9/24/15.
 */
public class KeyboardEditText extends EditText {

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

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

    public KeyboardEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        if (listener != null)
            listener.onStateChanged(this, true);
    }

    @Override
    public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
                && event.getAction() == KeyEvent.ACTION_UP) {
            if (listener != null)
                listener.onStateChanged(this, false);
        }
        return super.onKeyPreIme(keyCode, event);
    }

    /**
     * Keyboard Listener
     */
    KeyboardListener listener;

    public void setOnKeyboardListener(KeyboardListener listener) {
        this.listener = listener;
    }

    public interface KeyboardListener {
        void onStateChanged(KeyboardEditText keyboardEditText, boolean showing);
    }
}

android - Detecting when user has dismissed the soft keyboard - Stack ...

android
Rectangle 27 13

Here is my custom EditText to detect whether keyboard is showing or not

/**
 * Created by TheFinestArtist on 9/24/15.
 */
public class KeyboardEditText extends EditText {

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

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

    public KeyboardEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        if (listener != null)
            listener.onStateChanged(this, true);
    }

    @Override
    public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
                && event.getAction() == KeyEvent.ACTION_UP) {
            if (listener != null)
                listener.onStateChanged(this, false);
        }
        return super.onKeyPreIme(keyCode, event);
    }

    /**
     * Keyboard Listener
     */
    KeyboardListener listener;

    public void setOnKeyboardListener(KeyboardListener listener) {
        this.listener = listener;
    }

    public interface KeyboardListener {
        void onStateChanged(KeyboardEditText keyboardEditText, boolean showing);
    }
}

android - Detecting when user has dismissed the soft keyboard - Stack ...

android
Rectangle 27 17

I made a slight change on Jay's solution by calling super.onKeyPreIme():

_e = new EditText(inflater.getContext()) {
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK){
            cancelTextInput();
        }
        return super.onKeyPreIme(keyCode, event);
    }
};

android - Detecting when user has dismissed the soft keyboard - Stack ...

android
Rectangle 27 17

I made a slight change on Jay's solution by calling super.onKeyPreIme():

_e = new EditText(inflater.getContext()) {
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK){
            cancelTextInput();
        }
        return super.onKeyPreIme(keyCode, event);
    }
};

android - Detecting when user has dismissed the soft keyboard - Stack ...

android
Rectangle 27 53

for all versions

contentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {

    Rect r = new Rect();
    contentView.getWindowVisibleDisplayFrame(r);
    int screenHeight = contentView.getRootView().getHeight();

    // r.bottom is the position above soft keypad or device button.
    // if keypad is shown, the r.bottom is smaller than that before.
    int keypadHeight = screenHeight - r.bottom;

    Log.d(TAG, "keypadHeight = " + keypadHeight);

    if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
        // keyboard is opened
    }
    else {
        // keyboard is closed
    }
}
});

The only thing that worked on Android 6. Thanks.

@Code-Apprentice In the activity/fragment you're looking to respond to soft keyboard changes. ContentView is the root view of the layout of this activity/fragment.

How do I Detect if Software Keyboard is Visible on Android Device? - S...

android keyboard
Rectangle 27 51

for all versions

contentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {

    Rect r = new Rect();
    contentView.getWindowVisibleDisplayFrame(r);
    int screenHeight = contentView.getRootView().getHeight();

    // r.bottom is the position above soft keypad or device button.
    // if keypad is shown, the r.bottom is smaller than that before.
    int keypadHeight = screenHeight - r.bottom;

    Log.d(TAG, "keypadHeight = " + keypadHeight);

    if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
        // keyboard is opened
    }
    else {
        // keyboard is closed
    }
}
});

The only thing that worked on Android 6. Thanks.

@Code-Apprentice In the activity/fragment you're looking to respond to soft keyboard changes. ContentView is the root view of the layout of this activity/fragment.

How do I Detect if Software Keyboard is Visible on Android Device? - S...

android keyboard
Rectangle 27 4

Just create a class that extends Edittext and use that edittext in your code, you should just override the following method in the custom edittext:

@Override
 public boolean onKeyPreIme(int keyCode, KeyEvent event) {
 if (keyCode == KeyEvent.KEYCODE_BACK) {

    //Here it catch all back keys
    //Now you can do what you want.

} else if (keyCode == KeyEvent.KEYCODE_MENU) {
    // Eat the event
    return true;
}
return false;}

Is there a way to detect when keyboard opens?

android - Detecting when user has dismissed the soft keyboard - Stack ...

android
Rectangle 27 4

Just create a class that extends Edittext and use that edittext in your code, you should just override the following method in the custom edittext:

@Override
 public boolean onKeyPreIme(int keyCode, KeyEvent event) {
 if (keyCode == KeyEvent.KEYCODE_BACK) {

    //Here it catch all back keys
    //Now you can do what you want.

} else if (keyCode == KeyEvent.KEYCODE_MENU) {
    // Eat the event
    return true;
}
return false;}

Is there a way to detect when keyboard opens?

android - Detecting when user has dismissed the soft keyboard - Stack ...

android
Rectangle 27 6

There is (ridiculously) no simple, reliable way to do this. It can however be achieved in two parts, with a layout listener as suggested here. It's a little bit of a hack but it works:

mRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        Rect measureRect = new Rect(); //you should cache this, onGlobalLayout can get called often
        mRootView.getWindowVisibleDisplayFrame(measureRect);
        // measureRect.bottom is the position above soft keypad
        int keypadHeight = mRootView.getRootView().getHeight() - measureRect.bottom;

        if (keypadHeight > 0) {
            // keyboard is opened 
            mIsKeyboardVisible = true;
            mMyDependentView.setVisibility(View.GONE);
        } else {
            //store keyboard state to use in onBackPress if you need to
            mIsKeyboardVisible = false;
            mMyDependentView.setVisibility(View.VISIBLE);
        }
    }
});

giving +1 as it looks interesting and promising, but it probably won't work with apps running not-on-entire-screen... a bit a hack, but not so universal

True, you could get around that by caching a screenheight when you know the state of the keyboard is hidden, but that still breaks if a user goes splitscreen later

Android detect soft keyboard closing - Stack Overflow

android keyboard
Rectangle 27 6

just checked the code from that question (which actually come from the provided question and answered by Labeeb P) with the test project with just two edits on layout and it seems to work just fine - I'm able to receive delete even if edit is empty.

final EditText edit1 = (EditText) findViewById(R.id.editText1);

    edit1.setOnKeyListener(new View.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
                Log.e("IME_TEST", "DEL KEY");
            }
            return false;
        }
    });

This method works only for HW keyboard.

strange, because then I've checked it (more than 6 months ago) it was working fine on nexus one device.

Neither on 4.2.2 But it doesn't work with Android stock virtual keyboard. I also have Swiftkey keyboard and I'm able to receive KEYCODE_DEL on OnKeyListener.

android - Detect delete button in soft keyboard - Stack Overflow

android android-edittext android-softkeyboard
Rectangle 27 5

A simpler solution to this that I stumbled upon is using an InputFilter. InputFilter's filter() method appears to report all soft keyboard events - even those where the EditText's value isn't changing.

private InputFilter filter = (charSequence, start, end, dest, dStart, dEnd) -> {

    if (end == 0 || dStart < dEnd) {
        // backspace was pressed! handle accordingly
    }

    return charSequence;
};

...

myEditText.setFilters(new InputFilter[] { filter });

Backspace events can be evaluated using end, dStart, and dEnd. dStart will always be less than dEnd if a character was deleted. If the EditText is empty, you can still evaluate backspace presses by checking if end == 0.

Note that bulk deletes will also be caught in this if statement, so you may want to do some extra checking withing filter(). Also note that if you're using your computer keyboard to type into EditTexts in emulators, you can get unexpected results. Best to click software buttons for testing.

Doesn't work. Tried this only gets called when u delete the last cha from edit text. But don't get it when user press on delete on empty edit text.

@John Thanks for mentioning this. I updated the answer to correctly report. R.e. pressing delete on an empty edit text, is this happening on a real phone or emulator? If you're using your computer's 'backspace' to trigger deletes, you'll probably get unexpected results. Best to manually click the emulator's software buttons.

android - Detect delete button in soft keyboard - Stack Overflow

android android-edittext android-softkeyboard
Rectangle 27 13

/**
 * This class overrides the onKeyPreIme method to dispatch a key event if the
 * KeyEvent passed to onKeyPreIme has a key code of KeyEvent.KEYCODE_BACK.
 * This allows key event listeners to detect that the soft keyboard was
 * dismissed.
 *
 */
public class ExtendedEditText extends EditText {

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

    }

    public ExtendedEditText(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public ExtendedEditText(Context context) {
        super(context);

    }

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            dispatchKeyEvent(event);
            return false;
        }
        return super.onKeyPreIme(keyCode, event);
    }

}

@Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { // User has pressed Back key. So hide the keyboard InputMethodManager mgr = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); mgr.hideSoftInputFromWindow(this.getWindowToken(), 0); // TODO: Hide your view as you do it in your activity } return false; }

Did try to use this...but the activity gets finished as soon as back is pressed.I want the activity to get finished on the second time I press back..On first backpress,Dismiss keyboard and setCursorVisible(false) is what i am expecting.

Did return true instead of return false, and it solved my problem of activity getting finished. Nice solution..!!!

Detect dismiss keyboard event in Android - Stack Overflow

android android-edittext android-softkeyboard android-input-method
Rectangle 27 13

/**
 * This class overrides the onKeyPreIme method to dispatch a key event if the
 * KeyEvent passed to onKeyPreIme has a key code of KeyEvent.KEYCODE_BACK.
 * This allows key event listeners to detect that the soft keyboard was
 * dismissed.
 *
 */
public class ExtendedEditText extends EditText {

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

    }

    public ExtendedEditText(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public ExtendedEditText(Context context) {
        super(context);

    }

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            dispatchKeyEvent(event);
            return false;
        }
        return super.onKeyPreIme(keyCode, event);
    }

}

@Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { // User has pressed Back key. So hide the keyboard InputMethodManager mgr = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); mgr.hideSoftInputFromWindow(this.getWindowToken(), 0); // TODO: Hide your view as you do it in your activity } return false; }

Did try to use this...but the activity gets finished as soon as back is pressed.I want the activity to get finished on the second time I press back..On first backpress,Dismiss keyboard and setCursorVisible(false) is what i am expecting.

Did return true instead of return false, and it solved my problem of activity getting finished. Nice solution..!!!

Detect dismiss keyboard event in Android - Stack Overflow

android android-edittext android-softkeyboard android-input-method
Rectangle 27 3

import java.util.Random;

import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;
import android.widget.EditText;
/**
 * Created by mkallingal on 4/25/2016.
 */
public class CustomEditText extends EditText {

    private Random r = new Random();

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

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

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

    public void setRandomBackgroundColor() {

    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        return new ZanyInputConnection(super.onCreateInputConnection(outAttrs),
                true);
    }

    private class ZanyInputConnection extends InputConnectionWrapper {

        public ZanyInputConnection(InputConnection target, boolean mutable) {
            super(target, mutable);
        }

        @Override
        public boolean sendKeyEvent(KeyEvent event) {
            if (event.getAction() == KeyEvent.ACTION_DOWN
                    && event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
                CustomEditText.this.setRandomBackgroundColor();
                // Un-comment if you wish to cancel the backspace:
                // return false;
            }
            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);
        }

    }
}

Now you can use it in your Activity like so:

final CustomEditText _EditText = new CustomEditText(_Context);

     _EditText.setOnKeyListener(new View.OnKeyListener() {
                    @Override
                    public boolean onKey(View v, int keyCode, KeyEvent event) {
                        if (keyCode == KeyEvent.KEYCODE_DEL) {
                            String _text=_EditText.getText().toString();
                            if(StringUtils.isBlank(_text))
                                 //EditText is now empty
                            }
                        }
                        return false;
                    }
                });

android - Detect delete button in soft keyboard - Stack Overflow

android android-edittext android-softkeyboard
Rectangle 27 6

/**
* To capture the result of IMM hide/show soft keyboard
*/
public class IMMResult extends ResultReceiver {
     public int result = -1;
     public IMMResult() {
         super(null);
}

@Override 
public void onReceiveResult(int r, Bundle data) {
    result = r;
}

// poll result value for up to 500 milliseconds
public int getResult() {
    try {
        int sleep = 0;
        while (result == -1 && sleep < 500) {
            Thread.sleep(100);
            sleep += 100;
        }
    } catch (InterruptedException e) {
        Log.e("IMMResult", e.getMessage());
    }
    return result;
}
}
public boolean isSoftKeyboardShown(InputMethodManager imm, View v) {

    IMMResult result = new IMMResult();
    int res;

    imm.showSoftInput(v, 0, result);

    // if keyboard doesn't change, handle the keypress
    res = result.getResult();
    if (res == InputMethodManager.RESULT_UNCHANGED_SHOWN ||
            res == InputMethodManager.RESULT_UNCHANGED_HIDDEN) {

        return true;
    }
    else
        return false;

}

You may then use this to test all fields (EditText, AutoCompleteTextView, etc) that may have opened a softkeyboard:

InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
    if(isSoftKeyboardShown(imm, editText1) | isSoftKeyboardShown(imm, autocompletetextview1))
        //close the softkeyboard
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

Addmittely not an ideal solution, but it gets the job done.

This works. If you implement as singelton you can apply to all edittexts on focus change and have one global keyboard listener

Cannot resolve method 'getActivity()'

How do I Detect if Software Keyboard is Visible on Android Device? - S...

android keyboard