Android中EditText无法输入字符,移除指定代码可恢复功能求助
问题分析
问题根源在于调用orderAdapter.notifyDataSetChanged()刷新列表时,触发了布局重绘,导致EditText失去焦点、光标位置丢失甚至文本被意外重置,最终输入的字符无法正常显示。
解决方案
方案1:保存并恢复EditText状态
在刷新适配器前后,保存EditText的当前文本和光标位置,刷新后立即恢复状态,确保EditText保持输入状态:
修改loadSearchFilterData()方法:
private void loadSearchFilterData() { // 1. 保存EditText当前的文本和光标位置 String currentInput = selectedValue.getText().toString(); int cursorStart = selectedValue.getSelectionStart(); int cursorEnd = selectedValue.getSelectionEnd(); if (!selectedValue.getText().toString().isEmpty()) { String s = selectedValue.getText().toString(); List<BoOrderBookDao> filterList = new ArrayList<>(); for (int i = 0; i < sortedFilteredList.size(); i++) { if (sortedFilteredList.get(i).getDpVal().toLowerCase().contains(s.toLowerCase())) { filterList.add(sortedFilteredList.get(i)); } } orderBookModel.clear(); orderBookModel.addAll(filterList); } else { orderBookModel.clear(); orderBookModel.addAll(sortedFilteredList); } if (orderBookModel.size() == 0) { setErrorMsg(mContext.getResources().getString(R.string.no_data_available_txt)); } else { itemListLayout.setVisibility(View.VISIBLE); errorScrollview.setVisibility(View.GONE); } if (orderAdapter != null) { orderAdapter.requestType = requestType; orderAdapter.notifyDataSetChanged(); } // 2. 恢复EditText的文本和光标位置,重新获取焦点 selectedValue.setText(currentInput); selectedValue.setSelection(cursorStart, cursorEnd); selectedValue.requestFocus(); }
方案2:优化适配器刷新(可选)
使用DiffUtil替代notifyDataSetChanged(),只刷新列表中实际变化的项,减少布局重绘范围,从根源避免EditText失焦问题:
- 创建DiffUtil回调类:
public class OrderBookDiffCallback extends DiffUtil.Callback { private List<BoOrderBookDao> oldList; private List<BoOrderBookDao> newList; public OrderBookDiffCallback(List<BoOrderBookDao> oldList, List<BoOrderBookDao> newList) { this.oldList = oldList; this.newList = newList; } @Override public int getOldListSize() { return oldList.size(); } @Override public int getNewListSize() { return newList.size(); } @Override public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { // 根据实体类唯一标识判断是否为同一项,比如id return oldList.get(oldItemPosition).getId() == newList.get(newItemPosition).getId(); } @Override public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { // 判断内容是否一致,可根据实体类字段补充 BoOrderBookDao oldItem = oldList.get(oldItemPosition); BoOrderBookDao newItem = newList.get(newItemPosition); return oldItem.getDpVal().equals(newItem.getDpVal()); } }
- 修改
loadSearchFilterData()中的刷新逻辑:
if (orderAdapter != null) { orderAdapter.requestType = requestType; // 计算差异并局部刷新 List<BoOrderBookDao> newData = selectedValue.getText().toString().isEmpty() ? sortedFilteredList : filterList; DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new OrderBookDiffCallback(orderBookModel, newData)); orderBookModel.clear(); orderBookModel.addAll(newData); diffResult.dispatchUpdatesTo(orderAdapter); }
方案3:延迟执行搜索逻辑(可选)
添加输入延迟,避免用户每输入一个字符就立即触发刷新,减少布局重绘频率:
- 定义Handler和Runnable:
private Handler handler = new Handler(Looper.getMainLooper()); private Runnable searchRunnable;
- 修改TextWatcher的
afterTextChanged方法:
@Override public void afterTextChanged(Editable s) { if (!selectedAssetType.equals(OrderBookTypes.MUTUAL_FUND_TYPE)) { // 移除之前的延迟任务,避免重复执行 if (searchRunnable != null) { handler.removeCallbacks(searchRunnable); } // 延迟500ms执行搜索,可按需调整时长 searchRunnable = () -> loadSearchFilterData(); handler.postDelayed(searchRunnable, 500); } }
内容的提问来源于stack exchange,提问作者Bhaskar Jyoti Dutta
相关产品推荐
相关产品推荐

