列表行EditText焦点跳转异常:无法在数值输入框输入内容
解决ListView列表项中EditText光标自动跳回的问题
嘿,这个问题我之前做带EditText的ListView时也碰到过!核心原因是ListView的焦点机制和View复用在搞鬼,咱们一步步来搞定它:
问题根源
当你点击valueID输入框时,ListView会默认尝试抢夺焦点,再加上convertView复用的时候没处理好焦点状态,就导致光标直接跳回了nameID。另外你的布局里valueID没设置imeOptions,虽然不是直接原因,但也会影响输入体验,顺便一起优化了。
具体修复步骤
1. 给ListView添加焦点控制属性(关键一步)
在你的ListView布局里加上这几个属性,让子View优先获取焦点,阻止ListView抢焦点:
<ListView <!-- 保留你原有的其他属性 --> android:descendantFocusability="beforeDescendants" android:focusable="false" android:focusableInTouchMode="false" />
beforeDescendants这个属性就是告诉系统:先让子View处理焦点请求,ListView自己往后排。
2. 优化Adapter的getView方法,处理焦点与复用问题
ListView的View复用很容易搞乱EditText的状态,咱们得记录哪个item的输入框有焦点,复用的时候恢复它。
首先在Adapter类里加个成员变量,用来存储当前获取焦点的item位置:
private int focusedPosition = -1; // 记录当前获取焦点的item位置
然后修改你的getView方法:
@NonNull @Override public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) { SheetItem sheetItem = getItem(position); ViewHolder holder; if (convertView == null) { LayoutInflater inflater = LayoutInflater.from(getContext()); convertView = inflater.inflate(listItemLayout, parent, false); holder = new ViewHolder(); holder.name = convertView.findViewById(R.id.nameID); holder.value = convertView.findViewById(R.id.valueID); // 给数值输入框设置完成按钮,优化输入体验 holder.value.setImeOptions(EditorInfo.IME_ACTION_DONE); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } // 先把数据设置到输入框,避免复用导致显示错误内容 holder.name.setText(sheetItem.getName()); holder.value.setText(sheetItem.getValue()); // 恢复焦点:如果当前item之前有焦点,让对应的输入框重新获取焦点 if (position == focusedPosition) { holder.value.requestFocus(); } // 监听两个输入框的焦点变化,更新focusedPosition holder.name.setOnFocusChangeListener((v, hasFocus) -> { if (hasFocus) { focusedPosition = position; } }); holder.value.setOnFocusChangeListener((v, hasFocus) -> { if (hasFocus) { focusedPosition = position; } }); ImageButton deleteButton = convertView.findViewById(R.id.xButtonID); deleteButton.setTag(position); deleteButton.setOnClickListener(v -> { int pos = (int) v.getTag(); itemList.remove(pos); // 删除后如果焦点位置在删除位置之后,要往前挪一位 if (focusedPosition >= pos) { focusedPosition--; } notifyDataSetChanged(); }); return convertView; }
3. 优化布局中的EditText属性
给valueID补全几个属性,确保它能正常获取焦点:
<EditText android:id="@+id/valueID" android:layout_width="74dp" android:layout_height="44dp" android:layout_marginStart="8dp" android:ems="10" android:hint="Value" android:inputType="number|numberDecimal" app:layout_constraintStart_toEndOf="@+id/nameID" tools:layout_editor_absoluteY="176dp" android:imeOptions="actionDone" android:focusable="true" android:focusableInTouchMode="true" />
为什么这些修改有效?
android:descendantFocusability="beforeDescendants"彻底解决了ListView抢子View焦点的问题,让EditText能正常拿到焦点。- 记录
focusedPosition并在复用View时恢复焦点,避免因为convertView复用导致光标跑到错误的输入框里。 - 补全
imeOptions和焦点属性,让输入框的行为更符合预期,不会出现系统默认的奇怪焦点跳转。
内容的提问来源于stack exchange,提问作者Patroy
相关产品推荐
相关产品推荐

