Fragment中setOnFocusChangeListener未触发问题求助
从你的代码和布局来看,两个CustomAutoCompleteTextView的焦点监听逻辑几乎一致,但actvDivName的监听没触发,大概率是以下几个原因导致的,咱们逐一排查:
1. 异常捕获隐藏了真实问题
你给actvDivName的监听套了try-catch,但只打了日志——如果QRDivArrayAdapter还没初始化、或者调用getCount()/getItem(i)时抛出了空指针或其他异常,代码会直接跳转到catch块,不会执行清空文本的逻辑,而你可能没注意到Logcat里的异常日志。
排查&解决:
- 先去Logcat搜
eEmp/Resume标签,看看有没有异常信息; - 暂时去掉
try-catch,或者在catch里加个Toast提示,确认是否真的有异常抛出; - 确保
QRDivArrayAdapter在设置焦点监听之前,已经完成初始化并绑定到actvDivName上。
2. 父布局的焦点抢占
你的最外层LinearLayout设置了:
android:descendantFocusability="beforeDescendants" android:focusableInTouchMode="true"
这个配置会让容器优先获取焦点,可能拦截子控件的焦点变化事件。虽然actvEntryCategory正常,但可能因为触摸顺序或布局细节的差异,actvDivName的焦点事件被吞了。
解决:
- 尝试移除这两个属性,或者把
descendantFocusability改成afterDescendants:
android:descendantFocusability="afterDescendants"
- 给所有
TableRow统一加上android:focusableInTouchMode="false",避免行布局抢占焦点:
<TableRow android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:focusableInTouchMode="false">
3. 自定义控件的焦点逻辑干扰
你用的是自定义的CustomAutoCompleteTextView,如果这个类里重写了onFocusChanged但没调用父类方法,会导致外部设置的setOnFocusChangeListener失效。
排查:
- 打开
CustomAutoCompleteTextView的源码,检查是否有这样的代码:
@Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { // 自定义逻辑,但没调用super // super.onFocusChanged(focused, direction, previouslyFocusedRect); }
如果有,必须加上super.onFocusChanged(...),否则外部监听永远不会触发。
4. TextInputLayout的焦点冲突
TextInputLayout作为容器,可能会处理焦点事件,导致内部的AutoCompleteTextView监听没触发。
解决:
- 给
actvDivName显式加上焦点相关属性,确保它能正常获取焦点:
<com.efftronics.android.eEmployee.Common.UI.CustomAutoCompleteTextView android:id="@+id/actvDivName" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:hint="@string/station" android:inputType="textCapWords|textMultiLine" android:maxLength="250" android:focusable="true" android:focusableInTouchMode="true" app:hintTextAppearance="@style/AutocompleteTheme" />
- 也可以尝试给
input_layout_Division(actvDivName的父TextInputLayout)设置焦点监听,在里面判断actvDivName的焦点状态。
5. 先确认监听是否真的没触发
可以在actvDivName的监听开头加一行日志,确认监听是否真的没被调用:
Log.d("FocusTest", "actvDivName focus changed: " + b);
如果日志能打印,说明监听是触发的,只是后续逻辑有问题(比如适配器数据不匹配);如果没打印,再回到前面的原因排查。
内容的提问来源于stack exchange,提问作者sriram

