android:state_selected不生效的根本原因是view默认不自动维护selected状态,需手动调用setselected()触发,且selector中state顺序错误(兜底项在前)也会导致匹配失败。

selector 里 android:state_selected 不生效?先看 View 是否支持 selected 状态
很多同学加了 android:state_selected="true" 却没反应,根本原因是:不是所有 View 默认响应或维护 selected 状态。比如 TextView 默认不随点击切换 selected,Button 也不自动设 selected —— 它和 pressed、focused 是独立的状态机。
真正会主动更新 selected 的,通常是 AdapterView(如 ListView)里的子项,或你手动调用 view.setSelected(true) 的场景。
- 常见错误现象:
selector中写了android:state_selected="true",但点击/触摸后颜色/背景完全不变 - 必须确认:该 View 所在的容器是否设置了
android:choiceMode(如singleChoice),或者你是否在代码里显式调用了setSelected() -
RecyclerView中的 item 默认不管理selected,需自己用ViewHolder绑定状态,或配合SelectionTracker
XML selector 中 android:state_selected 和 android:state_activated 别混用
android:state_selected 是 View 自身的状态,靠调用 setSelected() 触发;而 android:state_activated 是由父容器(如 ListView 在 CHOICE_MODE_SINGLE 下)通过 setActivated() 设置的,生命周期更长、常用于“被选中并保持高亮”的场景(比如侧边栏菜单)。
- 如果你在
ListView里用setChoiceMode(CHOICE_MODE_SINGLE),它实际操作的是activated,不是selected—— 此时应优先用android:state_activated="true" - Android 3.0+ 推荐用
activated实现持久选中效果;selected更适合临时视觉反馈(例如某段文字被光标“选中”时) - 两者可共存,但顺序很重要:selector 中靠前的 item 优先匹配,建议把
state_activated放在state_selected前面,避免被覆盖
RecyclerView 里想用 android:state_selected,得自己接管状态
RecyclerView 不像 ListView 那样内置选择逻辑,它的 item View 默认不会被设为 selected,所以直接写 selector 没用。
- 最简做法:在
onBindViewHolder里根据数据模型判断是否选中,然后调用holder.itemView.setSelected(isSelected) - 别只改背景 —— 如果用了
android:background指向 selector,确保 selector 文件里对应 state 的 item 存在且路径正确(比如@drawable/bg_item_selector.xml) - 注意回收复用:
setSelected(false)必须在未选中分支里显式调用,否则滑动后会出现“多个 item 同时高亮”的错乱 - 如果项目支持 AndroidX,推荐用
SelectionTracker+ItemKeyProvider,它自动同步selected和 UI,但底层仍是调用setSelected()
selector 文件里写错顺序,state_selected 就永远不命中
selector 匹配是**从上到下第一个完全匹配的 item**,不是“最优匹配”。如果你把默认项(无任何 state 属性)放在最上面,后面所有带 state_selected 的都会被忽略。
- 错误写法:
<item android:drawable="@color/default_bg" /> <item android:state_selected="true" android:drawable="@color/selected_bg" />
→ 永远走第一条 - 正确顺序:把最具体的 state 放前面,兜底项放最后。例如:
<item android:state_selected="true" android:drawable="@color/selected_bg" /> <item android:state_pressed="true" android:drawable="@color/pressed_bg" /> <item android:drawable="@color/default_bg" />
- 调试技巧:临时把兜底项的
android:drawable设成明显颜色(如 bright red),滑动/点击后如果看到红色,说明前面的 state 根本没匹配上










