Fragment二次加载时Spinner的TextView setColor不生效问题
问题现象
- 需求:自定义Spinner将第一项作为提示占位项,选中第一项时对应TextView显示灰色,选中其余选项时文字显示黑色
- 异常表现:Fragment首次加载时颜色逻辑运行正常,通过导航按钮切换到其他Fragment再返回当前Fragment后,
setTextColor方法不再生效,TextView文字始终显示为黑色
原有实现代码
sexoSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View v, int position, long id) { if (v == null) { LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.item_gender, null); } iSexoSelected = position; switch (position) { case 0: ((TextView) v.findViewById(R.id.genderText)).setTextColor(getResources().getColor(R.color.gris_hint_fuente)); break; case 1: ((TextView) v.findViewById(R.id.genderText)).setTextColor(getResources().getColor(R.color.black)); sexoSeleccion = "Femenino"; break; case 2: ((TextView) v.findViewById(R.id.genderText)).setTextColor(getResources().getColor(R.color.black)); sexoSeleccion = "Masculino"; break; } } @Override public void onNothingSelected(AdapterView<?> parent) { } });
失效原因
- 核心错误1:
onItemSelected回调中增加了v == null时手动inflate布局的逻辑,手动inflate出的View不属于当前Spinner实际挂载的视图树,对这个View做的颜色修改完全不会同步到界面上。首次加载时回调返回的v是真实的选中项View所以改色生效,Fragment返回重建视图时,回调参数v的生命周期和手动inflate的View脱节,改色操作作用在无效View上自然失效。 - 核心错误2:混淆了Spinner的职责边界,选中项的View样式应该由Adapter负责渲染,
OnItemSelectedListener只需要处理选中后的业务逻辑(比如记录选中值、触发联动),不应该直接操作View样式,这种写法本身就不兼容View复用、重建的场景。
修复方案
- 精简
OnItemSelectedListener逻辑,移除所有操作View样式、手动inflate布局的代码,仅保留业务值记录逻辑:
sexoSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View v, int position, long id) { iSexoSelected = position; switch (position) { case 1: sexoSeleccion = "Femenino"; break; case 2: sexoSeleccion = "Masculino"; break; default: sexoSeleccion = ""; break; } } @Override public void onNothingSelected(AdapterView<?> parent) {} });
- 在Spinner绑定的自定义Adapter中重写
getView方法(该方法负责返回Spinner选中态展示的View,下拉列表项的样式可在getDropDownView中单独处理),在方法内根据position设置对应文字颜色:
@Override public View getView(int position, View convertView, ViewGroup parent) { TextView genderTv = (TextView) super.getView(position, convertView, parent); if (position == 0) { genderTv.setTextColor(getResources().getColor(R.color.gris_hint_fuente)); } else { genderTv.setTextColor(getResources().getColor(R.color.black)); } return genderTv; }
- 额外排查点:如果Fragment通过导航切换时会销毁视图重建,要确认Spinner的初始化、Adapter绑定、监听设置逻辑是放在
onViewCreated生命周期中执行,不要持有上一个视图周期的旧View引用。
内容的提问来源于stack exchange,提问作者Vincenzo Ravo
相关产品推荐
相关产品推荐

