Android ExpandableListView条目软键盘弹出时光标自动跳转问题
ExpandableListView 输入框焦点自动跳转问题解决方案
问题复现
我在应用中使用了ExpandableListView,此前项目中多次使用该组件均无运行异常,本次遇到如下问题:
- 点击折扣价、价格对应的输入框准备输入内容时,底部弹出数字键盘,光标会自动跳转到当前行的尺寸输入框中,该问题每次软键盘弹出时都会触发
已尝试方案缺陷
- 方案1:在AndroidManifest清单文件中为对应Activity设置
android:windowSoftInputMode="adjustNothing"属性该配置可以解决光标跳转问题,但部分列表内容会被软键盘遮挡,用户隐藏软键盘前无法查看被遮挡内容,体验极差
- 方案2:将价格输入框的
inputType属性设置为text该配置下软键盘仅会弹出一次,后续点击价格或折扣输入框时软键盘不会重新弹出,虽然不会触发光标跳转,但不符合数字输入的交互需求,无法正常使用
问题截图

根因分析
该问题本质是软键盘弹出触发Activity窗口重绘,ExpandableListView会重新调用getChildView()刷新可见区域的子Item布局。如果你没有在Adapter中正确保存和恢复每个输入框的焦点状态,重绘后系统会默认将焦点分配给当前Item布局中focusable优先级最高的第一个输入框,也就是你布局里排在前面的尺寸输入框。
你观察到的两种临时解决方案的逻辑也完全匹配该根因:
- 用
adjustNothing时窗口不会因为软键盘弹出触发重绘,所以不会触发Item刷新,自然不会出现焦点跳转 - 把
inputType改成text时系统不会重复触发软键盘弹出逻辑,也就不会触发窗口重绘,所以也不会复现问题
修复方案
你可以按以下步骤修复,不需要修改原有窗口配置和输入框输入类型,完全兼容原有交互逻辑:
- 在Adapter中定义变量保存当前获得焦点的输入框位置信息:
// 保存当前焦点所在的组位置、子位置、焦点输入框类型 private int currentFocusGroupPos = -1; private int currentFocusChildPos = -1; // 输入框类型可自定义:0=无焦点 1=尺寸输入框 2=价格输入框 3=折扣输入框 private int currentFocusViewType = 0;
- 给每个子Item的三个输入框设置
OnFocusChangeListener,当输入框获得焦点时更新上述保存的位置变量 - 在
getChildView()方法渲染完Item布局后,判断当前渲染的位置是否和保存的焦点位置一致,如果一致,手动给对应的输入框请求焦点:
// 此处为getChildView()内逻辑,groupPosition、childPosition为当前渲染项的位置 if (groupPosition == currentFocusGroupPos && childPosition == currentFocusChildPos) { switch (currentFocusViewType) { case 1: sizeEditText.requestFocus(); break; case 2: priceEditText.requestFocus(); break; case 3: discountEditText.requestFocus(); break; } }
- 可选优化:如果你的输入框内容需要持久化保存,也需要在Adapter中维护一份输入内容的缓存列表,在
getChildView()时给对应输入框赋值,避免重绘后内容丢失。
内容的提问来源于stack exchange,提问作者Zohab Ali
相关产品推荐
相关产品推荐

