state_focused 在触摸点击时无效,因 android 触摸模式下需同时满足 state_window_focused 和 state_focused 才能触发高亮态,selector 中必须联合判断二者,且聚焦项须置于默认项之前。

state_focused 在 Android selector 中对 EditText 无效——它只响应键盘导航(如方向键、Tab),不响应触摸点击获取焦点。
为什么点击 EditText 没触发 state_focused
Android 触摸模式下,用户点击输入框时系统默认进入“触摸模式”(isInTouchMode() == true),此时 state_focused 不会生效,必须用 state_window_focused + state_focused 组合判断。
-
state_focused:仅在键盘/方向键聚焦时为 true -
state_window_focused:窗口获得焦点时为 true(包括触摸点击后) - 两者同时为 true 才代表“当前可见且已获得焦点”,这才是你想要的“高亮态”
selector 中正确写法:用 state_window_focused 和 state_focused 联合判断
单独写 <item android:state_focused="true"> 几乎没用;必须加 <code>android:state_window_focused="true" 限定范围。
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="true" android:state_focused="true">
<shape>
<solid android:color="#E3F2FD" />
<stroke android:width="2dp" android:color="#2196F3" />
</shape>
</item>
<item>
<shape>
<solid android:color="#FFFFFF" />
<stroke android:width="1dp" android:color="#BDBDBD" />
</shape>
</item>
</selector>
- 第一项必须两个状态同时满足,否则触摸点击后样式不切换
- 顺序很重要:把“聚焦态”放在前面,否则默认项会覆盖它
- 别漏掉
android:state_window_focused="true",这是最常被忽略的条件
替代方案:直接监听 onFocusChange 更可控
XML selector 对复杂交互支持有限,比如要区分“刚获得焦点”和“正在输入中”,或者需要动画过渡,用代码更稳。
- 在 Java/Kotlin 中调用
editText.setOnFocusChangeListener - 在回调里根据
hasFocus参数手动设置背景:editText.setBackgroundResource(R.drawable.bg_edittext_focused) - 注意:不要在回调里反复
setBackgroundResource同一个资源——避免重复 inflate - 如果用了
MaterialEditText或TextInputLayout,优先走它的boxStrokeColor属性,不用自己写 selector
真正麻烦的是多状态叠加:比如既要处理 state_focused,又要兼容 state_error、state_enabled,这时候 XML selector 很容易互相覆盖。不如拆成两层——基础状态用 selector,动态状态(如错误)用代码控制背景叠加层。










