Reputation: 6019
Is there a way to get a reference to the view being touched while inside Activity.dispatchTouchEvent(MotionEvent ev)?
I need to hide a custom RelativeLayout "Keyboard" if user clicks anywhere where it is not an EditText. And since I am using on activity and many fragments each has many view groups and each group has it own many views, some of which are EditTexts, it would be too much work to set an onTouchEvent on each child view or child viewGroup.
In MainActivity, something like this is what I think would be a good way to go.
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mKeyboardLike.getVisibility() == View.VISIBLE) {
if (!isTouchedEditText(ev.getRawX(), ev.getRawY())) {
mKeyboardLike.setVisibility(View.GONE);
}
}
return super.dispatchTouchEvent(ev);
}
private boolean isTouchedEditText(int x, int y){//viewFound instanceOf EditText; return true;}
Upvotes: 0
Views: 2016
Reputation: 2417
Put the given Kotlin code in your activity.
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
val x = ev.x.roundToInt()
val y = ev.y.roundToInt()
val rootView = window?.decorView?.rootView
if (rootView is ViewGroup) {
for (i in 0 until rootView.childCount.orZero()) {
if (isEditText(x, y, rootView.getChildAt(i))) {
return super.dispatchTouchEvent(ev)
}
}
}
hideKeyboard()
return super.dispatchTouchEvent(ev)
}
fun isEditText(x: Int, y: Int, view: View): Boolean {
if (view is ViewGroup) {
for (i in 0 until view.childCount) {
if (isEditText(x, y, view.getChildAt(i))) {
return true
}
}
} else if (view is EditText || view is TextInputLayout) {
val rect = Rect()
view.getGlobalVisibleRect(rect)
if (x > rect.left && x < rect.right && y > rect.top && y < rect.bottom) {
return true
}
}
return false
}
It will check each nested view and if the touched view is EditText or TextInputLayout then it will not hide the keyboard, for all other cases, it will hide the keyboard.
It works for EditText in fragments as well.
Upvotes: 0
Reputation: 1004
I think this should help you:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int x = Math.round(ev.getX());
int y = Math.round(ev.getY());
for (int i = 0; i < getChildCount(); i++) {
if (isEditText(x, y, getChildAt(i))) {
return true;
}
}
return true;
}
public boolean isEditText(int x, int y, View view) {
if (view instanceof ViewGroup) {
for (int i = 0; i < getChildCount(); i++) {
if (isEditText(x, y, ((ViewGroup) view).getChildAt(i))) {
return true;
}
}
} else if (view instanceof EditText) {
if (x > view.getLeft() && x < view.getRight() && y > view.getTop() && y < view.getBottom()) {
return true;
}
}
return false;
}
Upvotes: 2