Skip to content

Instantly share code, notes, and snippets.

@felixdivo
Created June 14, 2016 22:24
Show Gist options
  • Save felixdivo/aebcad7e32444a8b126e9d544f42e0e9 to your computer and use it in GitHub Desktop.
Save felixdivo/aebcad7e32444a8b126e9d544f42e0e9 to your computer and use it in GitHub Desktop.
An android EditText view, that calls a listener if the user leaves the edit field. (Closes the keyboard or moves to another focus)
package com.example;
import android.content.Context;
import android.graphics.Rect;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.KeyEvent;
/**
* https://developer.android.com/reference/android/widget/TextView.OnEditorActionListener.html
* https://developer.android.com/reference/android/view/View.OnFocusChangeListener.html
* https://developer.android.com/reference/android/text/TextWatcher.html
* http://stackoverflow.com/questions/8063439/android-edittext-finished-typing-event
* http://stackoverflow.com/questions/4312319/howto-capture-the-virtual-keyboard-show-hide-event-in-android
* http://stackoverflow.com/questions/3425932/detecting-when-user-has-dismissed-the-soft-keyboard
*/
public class UserAwareEditText extends TypefaceEditText {
public UserAwareEditText(Context context) {
super(context);
init();
}
public UserAwareEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public UserAwareEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
isCurrentlyFocused = isFocused();
}
private boolean isCurrentlyFocused = false;
private boolean textHasChanged = false;
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
if (isCurrentlyFocused && !focused) // lost focus
userHasLeft();
isCurrentlyFocused = focused;
}
@Override
public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP)
userHasLeft();
return super.onKeyPreIme(keyCode, event);
}
@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
textHasChanged = true;
}
private synchronized void userHasLeft() {
if (!textHasChanged) {
if (userListener != null) userListener.userHasLeft(this, false);
} else {
// rest
textHasChanged = false;
if (userListener != null) userListener.userHasLeft(this, true);
}
}
private UserListener userListener;
public void setUserListener(UserListener userListener) {
this.userListener = userListener;
}
public interface UserListener {
void userHasLeft(UserAwareEditText userAwareEditText, boolean textWasEdited);
}
}
@felixdivo
Copy link
Author

felixdivo commented Jun 14, 2016

This does not work if the user presses "Done", you need to use something like this:

@Override
public void onEditorAction(int actionCode) 
{

super.onEditorAction(actionCode);

switch (actionCode) {
    case EditorInfo.IME_ACTION_DONE:
    case EditorInfo.IME_ACTION_GO:
    case EditorInfo.IME_ACTION_NEXT:
    case EditorInfo.IME_ACTION_PREVIOUS:
    case EditorInfo.IME_ACTION_SEARCH:
    case EditorInfo.IME_ACTION_SEND:
        userHasLeft();
        break;

    case EditorInfo.IME_ACTION_NONE:
    case EditorInfo.IME_ACTION_UNSPECIFIED:
    default:
        // ignore
        break;
}

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment