Description
I had this same issue and fixed it with the following changes. They trick was to allow the parent scroll view to grab focus whenever no other child view wants it. For this to work, the scrollview must be clickable and focusable. This is better than using onTouchEvent
or onInterceptTouchEvent
because the ScrollView needs to leverage those for fairly complex scrolling bahavior.
Code Changes
First, in your layout file add these attributes to the scrollview:
android:focusable="true"
android:focusableInTouchMode="true"
android:clickable="true"
Next, in your code add these listeners to your scrollview:
scrollableContent.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus) {
onClickAway();
}
}
});
//this second listener is probably unnecessary but I put it in just in case there are weird edge cases where the scrollView is clicked but failed to gain focus
scrollableContent.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onClickAway();
}
});
Finally, implement whatever behavior you desire when the user clicks away from the fields in your form:
/**
* Invoked when something is clicked that is not otherwise listening for click events, like when
* the user clicks outside of an EditText view.
*/
protected void onClickAway() {
//hide soft keyboard
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindowToken(), 0);
}
Results
With these changes in place, the scrollview will gain focus anytime it is clicked and, in response, it will hide the keyboard. Note that if any other fields that require the keyboard are clicked, they will take precedence and keyboard will remain unchanged (i.e. open). Also, you could add the XML attributes and listeners to the scrollView's child ViewGroup, instead, and although I haven't tested it, I'm sure that would work, just as well.