You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

列表行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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:42:02