Android在 ListView或RecyclerView 的item中EditText 设置imeOptions、imeActionId、imeActionLabel属性导致的异常分析与处理
在设置EditText中设置了这些ime的属性,在点击键盘的回车键时候,会导致
focus search returned a view that wasn't able to take focus!异常的出现
什么原因呢?
查看TextVie源码发现在点击键盘的回车键会通过EditableInputConnection
来执行onEditorAction
方法
public void onEditorAction(int actionCode) {
//设置了ime属性mEditor就不为空
final Editor.InputContentType ict = mEditor == null ? null : mEditor.mInputContentType;
if (ict != null) {
if (ict.onEditorActionListener != null) {
//利用这里的return解决异常
if (ict.onEditorActionListener.onEditorAction(this,
actionCode, null)) {
return;
}
}
if (actionCode == EditorInfo.IME_ACTION_NEXT) {
View v = focusSearch(FOCUS_FORWARD);
if (v != null) {
//异常原因
if (!v.requestFocus(FOCUS_FORWARD)) {
throw new IllegalStateException("focus search returned a view "
+ "that wasn't able to take focus!");
}
}
return;
} else if (actionCode == EditorInfo.IME_ACTION_PREVIOUS) {
View v = focusSearch(FOCUS_BACKWARD);
if (v != null) {
//异常原因
if (!v.requestFocus(FOCUS_BACKWARD)) {
throw new IllegalStateException("focus search returned a view "
+ "that wasn't able to take focus!");
}
}
return;
} else if (actionCode == EditorInfo.IME_ACTION_DONE) {
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null && imm.isActive(this)) {
imm.hideSoftInputFromWindow(getWindowToken(), 0);
}
return;
}
}
//省略不重要的代码
}
从代码可以看出actionCode == EditorInfo.IME_ACTION_PREVIOUS
和actionCode == EditorInfo.IME_ACTION_PREVIOUS
这里可能会出现异常,异常的原因是查询上一个或下一个view的焦点的时候失败了 抛出了异常
解决办法
这两处抛出异常的代码上方有个return,如果能保证
ict.onEditorActionListener.onEditorAction(this, actionCode, null)
永远为true那么异常代码就永远不会执行
即设置EditText的onEditorActionListener()
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
//可以根据需求获取下一个焦点还是上一个
View nextView = v.focusSearch(View.FOCUS_DOWN);
if (nextView != null) {
nextView.requestFocus(View.FOCUS_DOWN);
}
//这里一定要返回true
return true;
}
});