Android列表中EditText按回车按键后出现 focus search returned a view that wasn’t able to take focus!崩溃异常分析解决
文章目录
一、前言
Android系统有个bug:List或者RecyclerView列表中如果存在多个不同类型的Item,其中有Editext,如果在Edittext点击输入法对话框总的完成会出现崩溃。
虽然这种情况,比如少见,但是还是记录一下。
解决这个问题有几种方法,一个是输入法里面适配,一个是系统代码不抛出异常,还有一个就是应用里面规避这个报错。
二、分析解决
1、分析报错日志
[15:27:48.364]logcat | grep AndroidRuntime
[15:27:48.631]09-06 15:27:23.979 1109 1109 D AndroidRuntime: Shutting down VM
[15:27:48.642]09-06 15:27:23.980 1109 1109 E AndroidRuntime: FATAL EXCEPTION: main
[15:27:48.645]09-06 15:27:23.980 1109 1109 E AndroidRuntime: Process: com.skg.settings, PID: 1109
[15:27:48.655]09-06 15:27:23.980 1109 1109 E AndroidRuntime: java.lang.IllegalStateException: focus search returned a view that wasn't able to take focus!
[15:27:48.664]09-06 15:27:23.980 1109 1109 E AndroidRuntime: at android.widget.TextView.onKeyUp(TextView.java:9646)
[15:27:48.675]09-06 15:27:23.980 1109 1109 E AndroidRuntime: at android.view.KeyEvent.dispatch(KeyEvent.java:2962)
[15:27:48.686]09-06 15:27:23.980 1109 1109 E AndroidRuntime: at android.view.View.dispatchKeyEvent(View.java:15591)
[15:27:48.698]09-06 15:27:23.980 1109 1109 E AndroidRuntime: at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1968)
报错说的是焦点异常。
不清楚是系统故意这样的还是系统的bug!
报错的代码就在TextView.java里面
framework\base\core\java\android\widget\TextView.java
case KeyEvent.KEYCODE_NUMPAD_ENTER:
if (event.hasNoModifiers()) {
if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0
|| shouldAdvanceFocusOnEnter()) {
if (!hasOnClickListeners()) {
View v = focusSearch(FOCUS_DOWN);
if (v != null) {
if (!v.requestFocus(FOCUS_DOWN)) {
throw new IllegalStateException("focus search returned a view "
+ "that wasn't able to take focus!");
}
这里看到是Enter回车后,一些判断后抛出了异常。
这里不做具体分析。有兴趣的自己看看。
2、解决
(1)设置imeOptions属性
在EditText属性里设置 android:imeOptions=“actionUnspecified” . imeOptions就是控制回车键具体作用的属性
<EditText
android:id="@+id/title_content"
android:layout_width="0dp"
android:layout_height="60dp"
android:hint="请输入标题"
android:singleLine="true"
android:maxLength="20"
android:inputType="text"
android:imeOptions="actionUnspecified"
app:layout_constraintTop_toBottomOf="@id/cover_barrier"
app:layout_constraintLeft_toRightOf="@id/title"
app:layout_constraintRight_toRightOf="parent"/>
如果actionUnspecified属性设置后依然会报错,你可以尝试另外一个属性actionNone
(2)代码中设置监听事件
这种办法就是监听编辑器操作,然后将回车操作写成自己需要的功能.
mEditView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
return true;
}
});
注意需要返回 true 表示你已经处理过这个事件了.
其实还有其他规避方法,有兴趣自己看看后面那个 庖丁解BUG 过程。
如果想验证测试一下,可以试试下面这段列表代码:
3、一段示例代码
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RecyclerView rv = new RecyclerView(this);
LinearLayoutManager lm = new LinearLayoutManager(this);
rv.setLayoutManager(lm);
rv.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
DividerItemDecoration did = new DividerItemDecoration(this, lm.getOrientation());
rv.addItemDecoration(did);
ArrayList<Integer> data = new ArrayList<Integer>(10);
for (int i = 0; i < 13; i++) {
data.add(i);
}
rv.setAdapter(new MyAdapter(data));
setContentView(rv);
}
class MyAdapter extends RecyclerView.Adapter {
ArrayList<Integer> data;
int viewTypeTextView, viewTypeEditText, viewTypeCheckbox;
public MyAdapter(ArrayList<Integer> data) {
this.data = data;
viewTypeEditText = this.data.size() - 2;
viewTypeCheckbox = this.data.size() - 1;
}
@Override
public int getItemViewType(int position) {
if (position == data.size() - 2) {
return viewTypeEditText;
} else if (position == data.size() - 1) {
return viewTypeCheckbox;
} else {
return viewTypeTextView;
}
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
View view;
if (viewType == viewTypeEditText) {
view = buildEditText(viewGroup.getContext());
} else if (viewTypeCheckbox == viewType) {
view = buildCheckbox(viewGroup.getContext());
} else {
view = buildTextView(viewGroup.getContext());
}
return new MyHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, int position) {
}
@Override
public int getItemCount() {
return data.size();
}
private View buildTextView(Context context) {
TextView textView = new TextView(context);
textView.setText("文本项");
textView.setTextSize(20);
textView.setGravity(Gravity.CENTER);
textView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
textView.setPadding(0, 50, 0, 50);
return textView;
}
private View buildEditText(Context context) {
EditText editText = new EditText(context);
editText.setHint("输入框");
editText.setInputType(EditorInfo.TYPE_CLASS_NUMBER);
editText.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
return editText;
}
private View buildCheckbox(Context context) {
CheckBox checkBox = new CheckBox(context);
checkBox.setText("单选框");
return checkBox;
}
class MyHolder extends RecyclerView.ViewHolder {
public MyHolder(@NonNull View itemView) {
super(itemView);
}
}
}
}
在Edittext 中点击完成就会报错。
三、其他
其他博客的介绍:
Android开发 EditText按回车按键后出现 focus search returned a view that wasn’t able to take focus! 错误…
第一个:言简意赅,直接说明解决方案:
https://blog.csdn.net/weixin_30950237/article/details/102108266
第二个:庖丁解BUG:focus search returned a view that wasn’t able to take focus!
从根源上分析解决这个bug。
https://www.jianshu.com/p/9d107363cd68