Skip to content

Instantly share code, notes, and snippets.

@laoyur
Last active October 23, 2019 13:40
Show Gist options
  • Save laoyur/cce0f5c9f2c6a304fc466c22f44f64a5 to your computer and use it in GitHub Desktop.
Save laoyur/cce0f5c9f2c6a304fc466c22f44f64a5 to your computer and use it in GitHub Desktop.
hide keyboard on touching outside of EditText.
//author: laoyur
//inspired of http://stackoverflow.com/a/31021154
package com.laoyur.test;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
public class BaseActivity extends Activity {
private List<EditText> _edits;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean handleReturn = super.dispatchTouchEvent(ev);
//cache all EditTexts
if(_edits == null) {
final ViewGroup viewGroup = (ViewGroup) ((ViewGroup) this
.findViewById(android.R.id.content)).getChildAt(0);
_edits = Views.find(viewGroup, EditText.class);
}
View view = getCurrentFocus();
//try to hide keyboard only if some EditText is focused
if(ev.getAction() == MotionEvent.ACTION_DOWN && _edits.contains(view)) {
boolean touchOutsideEdits = true;
int x = (int) ev.getRawX(); //relative to screen
int y = (int) ev.getRawY();
for(EditText et : _edits) {
if(getLocationOnScreen(et).contains(x, y)) {
touchOutsideEdits = false;
break;
}
}
if(touchOutsideEdits) {
InputMethodManager input = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
input.hideSoftInputFromWindow(getWindow().getCurrentFocus()
.getWindowToken(), 0);
}
}
return handleReturn;
}
// a helper function to calc Rect relative to Screen
private Rect getLocationOnScreen(View view) {
Rect rect = new Rect();
int[] location = new int[2];
view.getLocationOnScreen(location);
rect.left = location[0];
rect.top = location[1];
rect.right = location[0] + view.getWidth();
rect.bottom = location[1] + view.getHeight();
return rect;
}
}
//http://android-wtf.com/2013/06/how-to-easily-traverse-any-view-hierarchy-in-android/?ckattempt=1
package com.laoyur.test;
import android.view.View;
import android.view.ViewGroup;
public class LayoutTraverser {
public interface Processor {
void process(View view);
}
private final Processor processor;
private LayoutTraverser(Processor processor) {
this.processor = processor;
}
public static LayoutTraverser build(Processor processor) {
return new LayoutTraverser(processor);
}
public void traverse(ViewGroup root) {
final int childCount = root.getChildCount();
for (int i = 0; i < childCount; ++i) {
final View child = root.getChildAt(i);
processor.process(child);
if (child instanceof ViewGroup) {
traverse((ViewGroup) child);
}
}
}
}
//http://android-wtf.com/2013/06/how-to-easily-traverse-any-view-hierarchy-in-android/?ckattempt=1
package com.laoyur.test;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
final public class Views {
private Views() {}
public static List<View> find(ViewGroup root, Object tag) {
FinderByTag finderByTag = new FinderByTag(tag);
LayoutTraverser.build(finderByTag).traverse(root);
return finderByTag.getViews();
}
public static <T extends View> List<T> find(ViewGroup root, Class<T> type) {
FinderByType<T> finderByType = new FinderByType<T>(type);
LayoutTraverser.build(finderByType).traverse(root);
return finderByType.getViews();
}
private static class FinderByTag implements LayoutTraverser.Processor {
private final Object searchTag;
private final List<View> views = new ArrayList<View>();
private FinderByTag(Object searchTag) {
this.searchTag = searchTag;
}
@Override
public void process(View view) {
Object viewTag = view.getTag();
if (viewTag != null && viewTag.equals(searchTag)) {
views.add(view);
}
}
private List<View> getViews() {
return views;
}
}
private static class FinderByType<T extends View> implements LayoutTraverser.Processor {
private final Class<T> type;
private final List<T> views;
private FinderByType(Class<T> type) {
this.type = type;
views = new ArrayList<T>();
}
@Override
@SuppressWarnings("unchecked")
public void process(View view) {
if (type.isInstance(view)) {
views.add((T) view);
}
}
public List<T> getViews() {
return views;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment